Scale reaction images explicitly.

Fixes #17459.
This commit is contained in:
John Preston 2021-12-31 00:28:11 +03:00
parent 9f1268b6c8
commit bb3c91aa44
3 changed files with 40 additions and 31 deletions

View File

@ -43,20 +43,31 @@ constexpr auto kButtonHideDelay = crl::time(200);
}
[[nodiscard]] QSize CountMaxSizeWithMargins(style::margins margins) {
const auto extended = QRect(
return QRect(
QPoint(),
st::reactionCornerSize
).marginsAdded(margins);
const auto scale = Button::ScaleForState(ButtonState::Active);
return QSize(
int(base::SafeRound(extended.width() * scale)),
int(base::SafeRound(extended.height() * scale)));
).marginsAdded(margins).size();
}
[[nodiscard]] QSize CountOuterSize() {
return CountMaxSizeWithMargins(st::reactionCornerShadow);
}
[[nodiscard]] int CornerImageSize(float64 scale) {
return int(base::SafeRound(st::reactionCornerImage * scale));
}
[[nodiscard]] QImage PrepareMaxOtherReaction(QImage image) {
const auto size = CornerImageSize(1.);
const auto factor = style::DevicePixelRatio();
auto result = image.scaled(
QSize(size, size) * factor,
Qt::IgnoreAspectRatio,
Qt::SmoothTransformation);
result.setDevicePixelRatio(factor);
return result;
}
} // namespace
Button::Button(
@ -264,13 +275,10 @@ Manager::Manager(
QWidget *wheelEventsTarget,
Fn<void(QRect)> buttonUpdate)
: _outer(CountOuterSize())
, _inner(QRectF({}, st::reactionCornerSize))
, _innerActive(QRect({}, CountMaxSizeWithMargins({})))
, _inner(QRect({}, st::reactionCornerSize))
, _buttonShowTimer([=] { showButtonDelayed(); })
, _buttonUpdate(std::move(buttonUpdate)) {
_inner.translate(QRectF({}, _outer).center() - _inner.center());
_innerActive.translate(
QRect({}, _outer).center() - _innerActive.center());
_inner.translate(QRect({}, _outer).center() - _inner.center());
const auto ratio = style::DevicePixelRatio();
_cacheInOutService = QImage(
@ -402,7 +410,7 @@ void Manager::setMainReactionImage(QImage image) {
loadOtherReactions();
}
QMarginsF Manager::innerMargins() const {
QMargins Manager::innerMargins() const {
return {
_inner.x(),
_inner.y(),
@ -411,12 +419,12 @@ QMarginsF Manager::innerMargins() const {
};
}
QRectF Manager::buttonInner() const {
QRect Manager::buttonInner() const {
return buttonInner(_button.get());
}
QRectF Manager::buttonInner(not_null<Button*> button) const {
return QRectF(button->geometry()).marginsRemoved(innerMargins());
QRect Manager::buttonInner(not_null<Button*> button) const {
return button->geometry().marginsRemoved(innerMargins());
}
void Manager::loadOtherReactions() {
@ -429,7 +437,7 @@ void Manager::loadOtherReactions() {
.media = icon->createMediaView(),
}).first->second;
if (const auto image = entry.media->getStickerLarge()) {
entry.image = image->original();
entry.image = PrepareMaxOtherReaction(image->original());
entry.media = nullptr;
} else if (!_otherReactionsLifetime) {
icon->session().downloaderTaskFinished(
@ -445,7 +453,7 @@ void Manager::checkOtherReactions() {
for (auto &[icon, entry] : _otherReactions) {
if (entry.media) {
if (const auto image = entry.media->getStickerLarge()) {
entry.image = image->original();
entry.image = PrepareMaxOtherReaction(image->original());
entry.media = nullptr;
} else {
all = false;
@ -663,14 +671,14 @@ void Manager::paintAllEmoji(
auto hq = PainterHighQualityEnabler(p);
const auto between = st::reactionCornerSkip;
const auto oneHeight = st::reactionCornerSize.height() + between;
const auto oneSize = st::reactionCornerImage * scale;
const auto oneSize = CornerImageSize(scale);
const auto expandUp = button->expandUp();
const auto shift = QPoint(0, oneHeight * (expandUp ? -1 : 1));
auto emojiPosition = mainEmojiPosition
+ QPoint(0, button->scroll() * (expandUp ? 1 : -1));
for (const auto &reaction : _list) {
const auto inner = QRectF(_inner).translated(emojiPosition);
const auto target = QRectF(
const auto inner = _inner.translated(emojiPosition);
const auto target = QRect(
inner.x() + (inner.width() - oneSize) / 2,
inner.y() + (inner.height() - oneSize) / 2,
oneSize,
@ -739,7 +747,7 @@ QRect Manager::validateShadow(
const auto center = _inner.center();
const auto add = style::ConvertScale(2.);
const auto shift = style::ConvertScale(1.);
const auto extended = _inner.marginsAdded({ add, add, add, add });
const auto extended = QRectF(_inner).marginsAdded({add, add, add, add});
p.setPen(Qt::NoPen);
p.setBrush(shadow);
p.translate(center);
@ -769,16 +777,18 @@ QRect Manager::validateEmoji(int frameIndex, float64 scale) {
p.setCompositionMode(QPainter::CompositionMode_Source);
p.fillRect(QRect(position, result.size() / ratio), Qt::transparent);
if (!_mainReactionImage.isNull()) {
const auto size = st::reactionCornerImage * scale;
const auto size = CornerImageSize(scale);
const auto inner = _inner.translated(position);
const auto target = QRectF(
const auto target = QRect(
inner.x() + (inner.width() - size) / 2,
inner.y() + (inner.height() - size) / 2,
size,
size);
auto hq = PainterHighQualityEnabler(p);
p.drawImage(target, _mainReactionImage);
p.drawImage(target, _mainReactionImage.scaled(
target.size() * ratio,
Qt::IgnoreAspectRatio,
Qt::SmoothTransformation));
}
_validEmoji[frameIndex] = true;

View File

@ -194,9 +194,9 @@ private:
const QRect &geometry,
const PaintContext &context);
[[nodiscard]] QMarginsF innerMargins() const;
[[nodiscard]] QRectF buttonInner() const;
[[nodiscard]] QRectF buttonInner(not_null<Button*> button) const;
[[nodiscard]] QMargins innerMargins() const;
[[nodiscard]] QRect buttonInner() const;
[[nodiscard]] QRect buttonInner(not_null<Button*> button) const;
void loadOtherReactions();
void checkOtherReactions();
[[nodiscard]] ClickHandlerPtr computeButtonLink(QPoint position) const;
@ -207,8 +207,7 @@ private:
std::vector<Data::Reaction> _list;
mutable std::vector<ClickHandlerPtr> _links;
QSize _outer;
QRectF _inner;
QRect _innerActive;
QRect _inner;
QImage _cacheInOutService;
QImage _cacheParts;
QImage _cacheForPattern;

View File

@ -978,7 +978,7 @@ reactionCornerSize: size(40px, 32px);
reactionCornerRadius: 14px;
reactionCornerCenter: point(12px, -12px);
reactionCornerImage: 24px;
reactionCornerShadow: margins(4px, 4px, 4px, 8px);
reactionCornerShadow: margins(4px, 8px, 4px, 8px);
reactionCornerActiveAreaPadding: margins(10px, 10px, 10px, 10px);
reactionCornerAddedHeightMax: 120px;