mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-18 23:27:09 +02:00
Round correctly distinct photos and extended media.
This commit is contained in:
parent
f3662f4873
commit
abdd126dcf
15 changed files with 268 additions and 169 deletions
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
Loading…
Add table
Reference in a new issue