Round correctly distinct photos and extended media.

This commit is contained in:
John Preston 2022-09-30 23:03:44 +04:00
parent f3662f4873
commit abdd126dcf
15 changed files with 268 additions and 169 deletions

View file

@ -424,7 +424,7 @@ void Document::draw(Painter &p, const PaintContext &context) const {
const auto corners = (isBubbleTop()
? (RectPart::TopLeft | RectPart::TopRight)
: RectParts())
| ((isBubbleBottom() && !Has<HistoryDocumentCaptioned>())
| ((isRoundedInBubbleBottom() && !Has<HistoryDocumentCaptioned>())
? (RectPart::BottomLeft | RectPart::BottomRight)
: RectParts());
draw(p, context, width(), LayoutMode::Full, corners);
@ -767,21 +767,19 @@ void Document::fillThumbnailOverlay(
Ui::BubbleRounding rounding,
const PaintContext &context) const {
using Corner = Ui::BubbleCornerRounding;
using Radius = Ui::CachedCornerRadius;
auto corners = Ui::CornersPixmaps();
const auto &st = context.st;
const auto set = [&](int index, const Ui::CornersPixmaps &from) {
corners.p[index] = from.p[index];
};
const auto lookup = [&](Corner corner) -> const Ui::CornersPixmaps & {
const auto lookup = [&](Corner corner) {
switch (corner) {
case Corner::None: return st->msgSelectOverlayCornersSmall();
case Corner::Small: return st->msgSelectOverlayCornersThumbSmall();
case Corner::Large: return st->msgSelectOverlayCornersThumbLarge();
case Corner::None: return Radius::Small;
case Corner::Small: return Radius::ThumbSmall;
case Corner::Large: return Radius::ThumbLarge;
}
Unexpected("Corner value in Document::fillThumbnailOverlay.");
};
for (auto i = 0; i != 4; ++i) {
corners.p[i] = lookup(rounding[i]).p[i];
corners.p[i] = st->msgSelectOverlayCorners(lookup(rounding[i])).p[i];
}
Ui::FillComplexOverlayRect(p, rect, st->msgSelectOverlay(), corners);
}

View file

@ -90,7 +90,7 @@ void ExtendedPreview::ensureThumbnailRead() const {
}
_inlineThumbnail = Images::FromInlineBytes(bytes);
if (_inlineThumbnail.isNull()) {
_imageCacheInvalid = 1;
_imageCacheInvalid = true;
} else {
history()->owner().registerHeavyViewPart(_parent);
}
@ -202,6 +202,10 @@ void ExtendedPreview::draw(Painter &p, const PaintContext &context) const {
auto bubble = _parent->hasBubble();
auto captionw = paintw - st::msgPadding.left() - st::msgPadding.right();
auto rthumb = style::rtlrect(paintx, painty, paintw, painth, width());
const auto inWebPage = (_parent->media() != this);
const auto rounding = inWebPage
? std::optional<Ui::BubbleRounding>()
: adjustedBubbleRoundingWithCaption(_caption);
if (bubble) {
if (!_caption.isEmpty()) {
painth -= st::mediaCaptionSkip + _caption.countHeight(captionw);
@ -211,21 +215,15 @@ void ExtendedPreview::draw(Painter &p, const PaintContext &context) const {
rthumb = style::rtlrect(paintx, painty, paintw, painth, width());
}
} else {
// #TODO rounding
Ui::FillRoundShadow(p, 0, 0, paintw, painth, sti->msgShadow, sti->msgShadowCornersSmall);
Assert(rounding.has_value());
fillImageShadow(p, rthumb, *rounding, context);
}
const auto inWebPage = (_parent->media() != this);
const auto roundRadius = inWebPage
? ImageRoundRadius::Small
: ImageRoundRadius::Large;
const auto roundCorners = inWebPage ? RectPart::AllCorners : ((isBubbleTop() ? (RectPart::TopLeft | RectPart::TopRight) : RectPart::None)
| ((isRoundedInBubbleBottom() && _caption.isEmpty()) ? (RectPart::BottomLeft | RectPart::BottomRight) : RectPart::None));
validateImageCache(rthumb.size(), roundRadius, roundCorners);
validateImageCache(rthumb.size(), rounding);
p.drawImage(rthumb.topLeft(), _imageCache);
fillSpoilerMess(p, rthumb, roundRadius, roundCorners, context);
fillSpoilerMess(p, rthumb, rounding, context);
paintButton(p, rthumb, context);
if (context.selected()) {
Ui::FillComplexOverlayRect(p, st, rthumb, roundRadius, roundCorners);
fillImageOverlay(p, rthumb, rounding, context);
}
// date
@ -265,26 +263,16 @@ void ExtendedPreview::draw(Painter &p, const PaintContext &context) const {
void ExtendedPreview::validateImageCache(
QSize outer,
ImageRoundRadius radius,
RectParts corners) const {
const auto intRadius = static_cast<int>(radius);
const auto intCorners = static_cast<int>(corners);
std::optional<Ui::BubbleRounding> rounding) const {
const auto ratio = style::DevicePixelRatio();
if (_imageCache.size() == (outer * ratio)
&& _imageCacheRoundRadius == intRadius
&& _imageCacheRoundCorners == intCorners) {
&& _imageCacheRounding == rounding) {
return;
}
_imageCache = prepareImageCache(outer, radius, corners);
_imageCacheRoundRadius = intRadius;
_imageCacheRoundCorners = intCorners;
}
QImage ExtendedPreview::prepareImageCache(
QSize outer,
ImageRoundRadius radius,
RectParts corners) const {
return Images::Round(prepareImageCache(outer), radius, corners);
_imageCache = Images::Round(
prepareImageCache(outer),
MediaRoundingMask(rounding));
_imageCacheRounding = rounding;
}
QImage ExtendedPreview::prepareImageCache(QSize outer) const {
@ -295,8 +283,7 @@ QImage ExtendedPreview::prepareImageCache(QSize outer) const {
void ExtendedPreview::fillSpoilerMess(
QPainter &p,
QRect rect,
ImageRoundRadius radius,
RectParts corners,
std::optional<Ui::BubbleRounding> rounding,
const PaintContext &context) const {
if (!_animation) {
_animation = std::make_unique<Ui::SpoilerAnimation>([=] {
@ -310,8 +297,7 @@ void ExtendedPreview::fillSpoilerMess(
Ui::FillSpoilerRect(
p,
rect,
radius,
corners,
MediaRoundingMask(rounding),
spoiler.frame(index),
_cornerCache);
}

View file

@ -80,12 +80,7 @@ private:
bool needInfoDisplay() const;
void validateImageCache(
QSize outer,
ImageRoundRadius radius,
RectParts corners) const;
[[nodiscard]] QImage prepareImageCache(
QSize outer,
ImageRoundRadius radius,
RectParts corners) const;
std::optional<Ui::BubbleRounding> rounding) const;
[[nodiscard]] QImage prepareImageCache(QSize outer) const;
void paintButton(
Painter &p,
@ -95,8 +90,7 @@ private:
void fillSpoilerMess(
QPainter &p,
QRect rect,
ImageRoundRadius radius,
RectParts corners,
std::optional<Ui::BubbleRounding> rounding,
const PaintContext &context) const;
const not_null<Data::Invoice*> _invoice;
@ -109,9 +103,8 @@ private:
mutable QImage _buttonBackground;
mutable QColor _buttonBackgroundOverlay;
mutable Ui::Text::String _buttonText;
mutable int _imageCacheRoundRadius : 4 = 0;
mutable int _imageCacheRoundCorners : 12 = 0;
mutable int _imageCacheInvalid : 1 = 0;
mutable std::optional<Ui::BubbleRounding> _imageCacheRounding;
mutable bool _imageCacheInvalid = false;
};

View file

@ -163,8 +163,11 @@ void Location::draw(Painter &p, const PaintContext &context) const {
const auto sti = context.imageStyle();
const auto stm = context.messageStyle();
const auto hasText = !_title.isEmpty() || !_description.isEmpty();
const auto rounding = adjustedBubbleRounding(
hasText ? RectPart::FullTop : RectPart());
if (bubble) {
if (!_title.isEmpty() || !_description.isEmpty()) {
if (hasText) {
if (isBubbleTop()) {
painty += st::msgPadding.top();
}
@ -185,26 +188,34 @@ void Location::draw(Painter &p, const PaintContext &context) const {
painty += st::mediaInBubbleSkip;
}
painth -= painty;
} else {
// #TODO rounding
Ui::FillRoundShadow(p, 0, 0, paintw, painth, sti->msgShadow, sti->msgShadowCornersSmall);
}
auto rthumb = QRect(paintx, painty, paintw, painth);
if (!bubble) {
fillImageShadow(p, rthumb, rounding, context);
}
auto roundRadius = ImageRoundRadius::Large;
auto roundCorners = ((isBubbleTop() && _title.isEmpty() && _description.isEmpty()) ? (RectPart::TopLeft | RectPart::TopRight) : RectPart::None)
| (isRoundedInBubbleBottom() ? (RectPart::BottomLeft | RectPart::BottomRight) : RectPart::None);
auto rthumb = QRect(paintx, painty, paintw, painth);
ensureMediaCreated();
if (const auto thumbnail = _media->image()) {
p.drawPixmap(rthumb.topLeft(), thumbnail->pixSingle(
rthumb.size(),
{
.options = Images::RoundOptions(roundRadius, roundCorners),
.outer = rthumb.size(),
}));
} else {
Ui::FillComplexLocationRect(p, st, rthumb, roundRadius, roundCorners);
}
//if (const auto thumbnail = _media->image()) {
// p.drawPixmap(rthumb.topLeft(), thumbnail->pixSingle(
// rthumb.size(),
// {
// .options = Images::RoundOptions(roundRadius, roundCorners),
// .outer = rthumb.size(),
// }));
//} else if (!bubble) {
Ui::PaintBubble(
p,
Ui::SimpleBubble{
.st = context.st,
.geometry = rthumb,
.pattern = context.bubblesPattern,
.patternViewport = context.viewport,
.outerWidth = width(),
.selected = context.selected(),
.outbg = context.outbg,
.rounding = rounding,
});
//}
const auto paintMarker = [&](const style::icon &icon) {
icon.paint(
p,
@ -215,7 +226,7 @@ void Location::draw(Painter &p, const PaintContext &context) const {
paintMarker(st->historyMapPoint());
paintMarker(st->historyMapPointInner());
if (context.selected()) {
Ui::FillComplexOverlayRect(p, st, rthumb, roundRadius, roundCorners);
fillImageOverlay(p, rthumb, rounding, context);
}
if (_parent->media() == this) {

View file

@ -20,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/item_text_options.h"
#include "ui/chat/chat_style.h"
#include "ui/chat/message_bubble.h"
#include "ui/image/image_prepare.h"
#include "core/ui_integration.h"
#include "styles/style_chat.h"
@ -187,6 +188,60 @@ QSize Media::countCurrentSize(int newWidth) {
return QSize(qMin(newWidth, maxWidth()), minHeight());
}
void Media::fillImageShadow(
QPainter &p,
QRect rect,
Ui::BubbleRounding rounding,
const PaintContext &context) const {
const auto sti = context.imageStyle();
auto corners = Ui::CornersPixmaps();
const auto choose = [&](int index) -> QPixmap {
using Corner = Ui::BubbleCornerRounding;
switch (rounding[index]) {
case Corner::Large: return sti->msgShadowCornersLarge.p[index];
case Corner::Small: return sti->msgShadowCornersSmall.p[index];
}
return QPixmap();
};
corners.p[2] = choose(2);
corners.p[3] = choose(3);
Ui::FillRoundShadow(p, rect, sti->msgShadow, corners);
}
void Media::fillImageOverlay(
QPainter &p,
QRect rect,
std::optional<Ui::BubbleRounding> rounding,
const PaintContext &context) const {
using Radius = Ui::CachedCornerRadius;
const auto &st = context.st;
if (!rounding) {
Ui::FillComplexOverlayRect(
p,
rect,
st->msgSelectOverlay(),
st->msgSelectOverlayCorners(Radius::Small));
return;
}
using Corner = Ui::BubbleCornerRounding;
auto corners = Ui::CornersPixmaps();
const auto lookup = [&](Corner corner) {
switch (corner) {
case Corner::None: return Radius::kCount;
case Corner::Small: return Radius::BubbleSmall;
case Corner::Large: return Radius::BubbleLarge;
}
Unexpected("Corner value in Document::fillThumbnailOverlay.");
};
for (auto i = 0; i != 4; ++i) {
const auto radius = lookup((*rounding)[i]);
corners.p[i] = (radius == Radius::kCount)
? QPixmap()
: st->msgSelectOverlayCorners(radius).p[i];
}
Ui::FillComplexOverlayRect(p, rect, st->msgSelectOverlay(), corners);
}
void Media::repaint() const {
history()->owner().requestViewRepaint(_parent);
}
@ -257,10 +312,59 @@ TextState Media::getStateGrouped(
Unexpected("Grouping method call.");
}
Ui::BubbleRounding Media::adjustedBubbleRounding(RectParts square) const {
auto result = bubbleRounding();
using Corner = Ui::BubbleCornerRounding;
const auto adjust = [&](bool round, Corner already, RectPart corner) {
return (already == Corner::Tail || !round || (square & corner))
? Corner::None
: already;
};
const auto top = isBubbleTop();
const auto bottom = isRoundedInBubbleBottom();
result.topLeft = adjust(top, result.topLeft, RectPart::TopLeft);
result.topRight = adjust(top, result.topRight, RectPart::TopRight);
result.bottomLeft = adjust(
bottom,
result.bottomLeft,
RectPart::BottomLeft);
result.bottomRight = adjust(
bottom,
result.bottomRight,
RectPart::BottomRight);
return result;
}
Ui::BubbleRounding Media::adjustedBubbleRoundingWithCaption(
const Ui::Text::String &caption) const {
return adjustedBubbleRounding(
caption.isEmpty() ? RectParts() : RectPart::FullBottom);
}
bool Media::isRoundedInBubbleBottom() const {
return isBubbleBottom()
&& !_parent->data()->repliesAreComments()
&& !_parent->data()->externalReply();
}
Images::CornersMaskRef MediaRoundingMask(
std::optional<Ui::BubbleRounding> rounding) {
using Radius = Ui::CachedCornerRadius;
if (!rounding) {
return Images::CornersMaskRef(Ui::CachedCornersMasks(Radius::Small));
}
using Corner = Ui::BubbleCornerRounding;
auto result = Images::CornersMaskRef();
const auto &small = Ui::CachedCornersMasks(Radius::BubbleSmall);
const auto &large = Ui::CachedCornersMasks(Radius::BubbleLarge);
for (auto i = 0; i != 4; ++i) {
switch ((*rounding)[i]) {
case Corner::Small: result.p[i] = &small[i]; break;
case Corner::Large: result.p[i] = &large[i]; break;
}
}
return result;
}
} // namespace HistoryView

View file

@ -32,8 +32,13 @@ struct ColorReplacements;
namespace Ui {
struct BubbleSelectionInterval;
struct ChatPaintContext;
struct CornersMaskRef;
} // namespace Ui
namespace Images {
struct CornersMaskRef;
} // namespace Images
namespace HistoryView {
enum class PointState : char;
@ -246,6 +251,10 @@ public:
[[nodiscard]] Ui::BubbleRounding bubbleRounding() const {
return _bubbleRounding;
}
[[nodiscard]] Ui::BubbleRounding adjustedBubbleRounding(
RectParts square = {}) const;
[[nodiscard]] Ui::BubbleRounding adjustedBubbleRoundingWithCaption(
const Ui::Text::String &caption) const;
[[nodiscard]] bool isBubbleTop() const {
return (_inBubbleState == MediaInBubbleState::Top)
|| (_inBubbleState == MediaInBubbleState::None);
@ -321,6 +330,17 @@ protected:
[[nodiscard]] bool usesBubblePattern(const PaintContext &context) const;
void fillImageShadow(
QPainter &p,
QRect rect,
Ui::BubbleRounding rounding,
const PaintContext &context) const;
void fillImageOverlay(
QPainter &p,
QRect rect,
std::optional<Ui::BubbleRounding> rounding, // nullopt if in WebPage.
const PaintContext &context) const;
void repaint() const;
const not_null<Element*> _parent;
@ -329,4 +349,7 @@ protected:
};
[[nodiscard]] Images::CornersMaskRef MediaRoundingMask(
std::optional<Ui::BubbleRounding> rounding);
} // namespace HistoryView

View file

@ -258,6 +258,9 @@ void Photo::draw(Painter &p, const PaintContext &context) const {
if (_serviceWidth > 0) {
paintUserpicFrame(p, context, rthumb.topLeft());
} else {
const auto rounding = inWebPage
? std::optional<Ui::BubbleRounding>()
: adjustedBubbleRoundingWithCaption(_caption);
if (bubble) {
if (!_caption.isEmpty()) {
painth -= st::mediaCaptionSkip + _caption.countHeight(captionw);
@ -267,19 +270,13 @@ void Photo::draw(Painter &p, const PaintContext &context) const {
rthumb = style::rtlrect(paintx, painty, paintw, painth, width());
}
} else {
// #TODO rounding
Ui::FillRoundShadow(p, 0, 0, paintw, painth, sti->msgShadow, sti->msgShadowCornersSmall);
Assert(rounding.has_value());
fillImageShadow(p, rthumb, *rounding, context);
}
const auto inWebPage = (_parent->media() != this);
const auto roundRadius = inWebPage
? ImageRoundRadius::Small
: ImageRoundRadius::Large;
const auto roundCorners = inWebPage ? RectPart::AllCorners : ((isBubbleTop() ? (RectPart::TopLeft | RectPart::TopRight) : RectPart::None)
| ((isRoundedInBubbleBottom() && _caption.isEmpty()) ? (RectPart::BottomLeft | RectPart::BottomRight) : RectPart::None));
validateImageCache(rthumb.size(), roundRadius, roundCorners);
validateImageCache(rthumb.size(), rounding);
p.drawImage(rthumb.topLeft(), _imageCache);
if (context.selected()) {
Ui::FillComplexOverlayRect(p, st, rthumb, roundRadius, roundCorners);
fillImageOverlay(p, rthumb, rounding, context);
}
}
if (radial || (!loaded && !_data->loading())) {
@ -355,32 +352,22 @@ void Photo::draw(Painter &p, const PaintContext &context) const {
void Photo::validateImageCache(
QSize outer,
ImageRoundRadius radius,
RectParts corners) const {
const auto intRadius = static_cast<int>(radius);
const auto intCorners = static_cast<int>(corners);
std::optional<Ui::BubbleRounding> rounding) const {
const auto large = _dataMedia->image(PhotoSize::Large);
const auto ratio = style::DevicePixelRatio();
const auto shouldBeBlurred = (large != nullptr) ? 0 : 1;
const auto shouldBeBlurred = !large;
if (_imageCache.size() == (outer * ratio)
&& _imageCacheRoundRadius == intRadius
&& _imageCacheRoundCorners == intCorners
&& _imageCacheRounding == rounding
&& _imageCacheBlurred == shouldBeBlurred) {
return;
}
_imageCache = prepareImageCache(outer, radius, corners);
_imageCacheRoundRadius = intRadius;
_imageCacheRoundCorners = intCorners;
_imageCache = Images::Round(
prepareImageCache(outer),
MediaRoundingMask(rounding));
_imageCacheRounding = rounding;
_imageCacheBlurred = shouldBeBlurred;
}
QImage Photo::prepareImageCache(
QSize outer,
ImageRoundRadius radius,
RectParts corners) const {
return Images::Round(prepareImageCache(outer), radius, corners);
}
QImage Photo::prepareImageCache(QSize outer) const {
using Size = PhotoSize;
const auto large = _dataMedia->image(Size::Large);

View file

@ -128,12 +128,7 @@ private:
not_null<QPixmap*> cache) const;
void validateImageCache(
QSize outer,
ImageRoundRadius radius,
RectParts corners) const;
[[nodiscard]] QImage prepareImageCache(
QSize outer,
ImageRoundRadius radius,
RectParts corners) const;
std::optional<Ui::BubbleRounding> rounding) const;
[[nodiscard]] QImage prepareImageCache(QSize outer) const;
bool videoAutoplayEnabled() const;
@ -155,9 +150,8 @@ private:
mutable std::unique_ptr<Streamed> _streamed;
mutable QImage _imageCache;
int _serviceWidth = 0;
mutable int _imageCacheRoundRadius : 4 = 0;
mutable int _imageCacheRoundCorners : 12 = 0;
mutable int _imageCacheBlurred : 1 = 0;
mutable std::optional<Ui::BubbleRounding> _imageCacheRounding;
mutable bool _imageCacheBlurred = false;
};

View file

@ -185,7 +185,7 @@ void ThemeDocument::draw(Painter &p, const PaintContext &context) const {
p,
rthumb,
st->msgSelectOverlay(),
st->msgSelectOverlayCornersSmall());
st->msgSelectOverlayCorners(Ui::CachedCornerRadius::Small));
}
if (_data) {

View file

@ -536,7 +536,7 @@ void WebPage::draw(Painter &p, const PaintContext &context) const {
p,
style::rtlrect(padding.left() + paintw - pw, tshift, pw, _pixh, width()),
st->msgSelectOverlay(),
st->msgSelectOverlayCornersSmall());
st->msgSelectOverlayCorners(Ui::CachedCornerRadius::Small));
}
paintw -= pw + st::webPagePhotoDelta;
}

View file

@ -161,24 +161,35 @@ void FillRoundRect(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color
FillRoundRect(p, x, y, w, h, bg, Corners[index], shadow, parts);
}
void FillRoundShadow(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color shadow, CachedRoundCorners index, RectParts parts) {
FillRoundShadow(p, x, y, w, h, shadow, Corners[index], parts);
void FillRoundShadow(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color shadow, CachedRoundCorners index) {
FillRoundShadow(p, x, y, w, h, shadow, Corners[index]);
}
void FillRoundShadow(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color shadow, const CornersPixmaps &corner, RectParts parts) {
auto cornerWidth = corner.p[0].width() / style::DevicePixelRatio();
auto cornerHeight = corner.p[0].height() / style::DevicePixelRatio();
if (parts & RectPart::Bottom) {
p.fillRect(x + cornerWidth, y + h, w - 2 * cornerWidth, st::msgShadow, shadow);
}
if (parts & RectPart::BottomLeft) {
p.fillRect(x, y + h - cornerHeight, cornerWidth, st::msgShadow, shadow);
p.drawPixmap(x, y + h - cornerHeight + st::msgShadow, corner.p[2]);
}
if (parts & RectPart::BottomRight) {
p.fillRect(x + w - cornerWidth, y + h - cornerHeight, cornerWidth, st::msgShadow, shadow);
p.drawPixmap(x + w - cornerWidth, y + h - cornerHeight + st::msgShadow, corner.p[3]);
void FillRoundShadow(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color shadow, const CornersPixmaps &corners) {
constexpr auto kLeft = 2;
constexpr auto kRight = 3;
const auto ratio = style::DevicePixelRatio();
const auto size = [&](int index) {
const auto &pix = corners.p[index];
return pix.isNull() ? 0 : (pix.width() / ratio);
};
const auto fillCorner = [&](int left, int bottom, int index) {
const auto &pix = corners.p[index];
if (pix.isNull()) {
return;
}
const auto size = pix.width() / ratio;
p.drawPixmap(left, bottom - size, pix);
};
const auto left = size(kLeft);
const auto right = size(kRight);
const auto from = x + left;
fillCorner(x, y + h + st::msgShadow, kLeft);
if (const auto width = w - left - right; width > 0) {
p.fillRect(from, y + h, width, st::msgShadow, shadow);
}
fillCorner(x + w - right, y + h + st::msgShadow, kRight);
}
CornersPixmaps PrepareCornerPixmaps(int32 radius, style::color bg, const style::color *sh) {
@ -219,21 +230,26 @@ void FillRoundRect(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color
FillRoundRect(p, x, y, w, h, bg, i->second, nullptr, parts);
}
[[nodiscard]] int CachedCornerRadiusValue(CachedCornerRadius tag) {
using Radius = CachedCornerRadius;
switch (tag) {
case Radius::Small: return st::roundRadiusSmall;
case Radius::ThumbSmall: return st::msgFileThumbRadiusSmall;
case Radius::ThumbLarge: return st::msgFileThumbRadiusLarge;
case Radius::BubbleSmall: return st::bubbleRadiusSmall;
case Radius::BubbleLarge: return st::bubbleRadiusLarge;
}
Unexpected("Radius tag in CachedCornerRadiusValue.");
}
[[nodiscard]] const std::array<QImage, 4> &CachedCornersMasks(
CachedCornerRadius radius) {
const auto index = static_cast<int>(radius);
Assert(index >= 0 && index < kCachedCornerRadiusCount);
if (CachedMasks[index][0].isNull()) {
using Radius = CachedCornerRadius;
const auto set = [](Radius key, int radius) {
CachedMasks[static_cast<int>(key)] = Images::CornersMask(radius);
};
set(Radius::Small, st::roundRadiusSmall);
set(Radius::ThumbSmall, st::msgFileThumbRadiusSmall);
set(Radius::ThumbLarge, st::msgFileThumbRadiusLarge);
set(Radius::BubbleSmall, st::bubbleRadiusSmall);
set(Radius::BubbleLarge, st::bubbleRadiusLarge);
CachedMasks[index] = Images::CornersMask(
CachedCornerRadiusValue(CachedCornerRadius(index)));
}
return CachedMasks[index];
}

View file

@ -40,9 +40,9 @@ void FillRoundRect(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color
inline void FillRoundRect(QPainter &p, const QRect &rect, style::color bg, CachedRoundCorners index, const style::color *shadow = nullptr, RectParts parts = RectPart::Full) {
FillRoundRect(p, rect.x(), rect.y(), rect.width(), rect.height(), bg, index, shadow, parts);
}
void FillRoundShadow(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color shadow, CachedRoundCorners index, RectParts parts = RectPart::Full);
inline void FillRoundShadow(QPainter &p, const QRect &rect, style::color shadow, CachedRoundCorners index, RectParts parts = RectPart::Full) {
FillRoundShadow(p, rect.x(), rect.y(), rect.width(), rect.height(), shadow, index, parts);
void FillRoundShadow(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color shadow, CachedRoundCorners index);
inline void FillRoundShadow(QPainter &p, const QRect &rect, style::color shadow, CachedRoundCorners index) {
FillRoundShadow(p, rect.x(), rect.y(), rect.width(), rect.height(), shadow, index);
}
void FillRoundRect(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color bg, ImageRoundRadius radius, RectParts parts = RectPart::Full);
inline void FillRoundRect(QPainter &p, const QRect &rect, style::color bg, ImageRoundRadius radius, RectParts parts = RectPart::Full) {
@ -61,9 +61,9 @@ void FillRoundRect(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color
inline void FillRoundRect(QPainter &p, const QRect &rect, style::color bg, const CornersPixmaps &corner, const style::color *shadow = nullptr, RectParts parts = RectPart::Full) {
return FillRoundRect(p, rect.x(), rect.y(), rect.width(), rect.height(), bg, corner, shadow, parts);
}
void FillRoundShadow(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color shadow, const CornersPixmaps &corner, RectParts parts = RectPart::Full);
inline void FillRoundShadow(QPainter &p, const QRect &rect, style::color shadow, const CornersPixmaps &corner, RectParts parts = RectPart::Full) {
FillRoundShadow(p, rect.x(), rect.y(), rect.width(), rect.height(), shadow, corner, parts);
void FillRoundShadow(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color shadow, const CornersPixmaps &corners);
inline void FillRoundShadow(QPainter &p, const QRect &rect, style::color shadow, const CornersPixmaps &corners) {
FillRoundShadow(p, rect.x(), rect.y(), rect.width(), rect.height(), shadow, corners);
}
enum class CachedCornerRadius {
@ -75,6 +75,7 @@ enum class CachedCornerRadius {
kCount,
};
[[nodiscard]] int CachedCornerRadiusValue(CachedCornerRadius tag);
[[nodiscard]] const std::array<QImage, 4> &CachedCornersMasks(
CachedCornerRadius radius);

View file

@ -492,7 +492,9 @@ void ChatStyle::assignPalette(not_null<const style::palette*> palette) {
_serviceBgCornersNormal = {};
_serviceBgCornersInverted = {};
_msgBotKbOverBgAddCorners = {};
_msgSelectOverlayCornersSmall = {};
for (auto &corners : _msgSelectOverlayCorners) {
corners = {};
}
for (auto &stm : _messageStyles) {
const auto same = (stm.textPalette.linkFg->c == stm.historyTextFg->c);
@ -550,7 +552,7 @@ const MessageImageStyle &ChatStyle::imageStyle(bool selected) const {
auto &result = imageStyleRaw(selected);
EnsureCorners(
result.msgDateImgBgCorners,
st::dateRadius,
(st::msgDateImgPadding.y() * 2 + st::normalFont->height) / 2,
result.msgDateImgBg);
EnsureCorners(
result.msgServiceBgCorners,
@ -575,28 +577,16 @@ const CornersPixmaps &ChatStyle::msgBotKbOverBgAddCorners() const {
return _msgBotKbOverBgAddCorners;
}
const CornersPixmaps &ChatStyle::msgSelectOverlayCornersSmall() const {
EnsureCorners(
_msgSelectOverlayCornersSmall,
st::roundRadiusSmall,
msgSelectOverlay());
return _msgSelectOverlayCornersSmall;
}
const CornersPixmaps &ChatStyle::msgSelectOverlayCorners(
CachedCornerRadius radius) const {
const auto index = static_cast<int>(radius);
Assert(index >= 0 && index < int(CachedCornerRadius::kCount));
const CornersPixmaps &ChatStyle::msgSelectOverlayCornersThumbSmall() const {
EnsureCorners(
_msgSelectOverlayCornersThumbSmall,
st::msgFileThumbRadiusSmall,
_msgSelectOverlayCorners[index],
CachedCornerRadiusValue(radius),
msgSelectOverlay());
return _msgSelectOverlayCornersThumbSmall;
}
const CornersPixmaps &ChatStyle::msgSelectOverlayCornersThumbLarge() const {
EnsureCorners(
_msgSelectOverlayCornersThumbLarge,
st::msgFileThumbRadiusLarge,
msgSelectOverlay());
return _msgSelectOverlayCornersThumbLarge;
return _msgSelectOverlayCorners[index];
}
MessageStyle &ChatStyle::messageStyleRaw(bool outbg, bool selected) const {

View file

@ -192,11 +192,8 @@ public:
[[nodiscard]] const MessageImageStyle &imageStyle(bool selected) const;
[[nodiscard]] const CornersPixmaps &msgBotKbOverBgAddCorners() const;
[[nodiscard]] const CornersPixmaps &msgSelectOverlayCornersSmall() const;
[[nodiscard]] auto msgSelectOverlayCornersThumbSmall() const
-> const CornersPixmaps &;
[[nodiscard]] auto msgSelectOverlayCornersThumbLarge() const
-> const CornersPixmaps &;
[[nodiscard]] const CornersPixmaps &msgSelectOverlayCorners(
CachedCornerRadius radius) const;
[[nodiscard]] const style::TextPalette &historyPsaForwardPalette() const {
return _historyPsaForwardPalette;
@ -322,9 +319,8 @@ private:
mutable std::array<MessageImageStyle, 2> _imageStyles;
mutable CornersPixmaps _msgBotKbOverBgAddCorners;
mutable CornersPixmaps _msgSelectOverlayCornersSmall;
mutable CornersPixmaps _msgSelectOverlayCornersThumbSmall;
mutable CornersPixmaps _msgSelectOverlayCornersThumbLarge;
mutable CornersPixmaps _msgSelectOverlayCorners[
int(CachedCornerRadius::kCount)];
style::TextPalette _historyPsaForwardPalette;
style::TextPalette _imgReplyTextPalette;

@ -1 +1 @@
Subproject commit f49ec866c11fc887d9b16435f67f756d523a9b5b
Subproject commit cec09b0260ba19639bf9abc7df373569aa1509e7