Use QImage bubbles background for some Media parts.

This commit is contained in:
John Preston 2021-08-20 13:12:07 +03:00
parent f4fdadd3b0
commit 784d57a2bc
36 changed files with 334 additions and 205 deletions

View File

@ -619,8 +619,7 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
.visibleAreaTop = _visibleAreaTop,
.visibleAreaTopGlobal = visibleAreaTopGlobal,
.clip = clip,
.initialShift = top,
});
}).translated(0, -top);
p.translate(0, top);
if (context.clip.y() < view->height()) while (top < drawToY) {
context.selection = itemRenderSelection(
@ -639,8 +638,7 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
const auto height = view->height();
top += height;
context.viewport.translate(0, -height);
context.clip.translate(0, -height);
context.translate(0, -height);
p.translate(0, height);
++iItem;
@ -672,8 +670,7 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
.clip = clip.intersected(
QRect(0, hdrawtop, width(), clip.top() + clip.height())
),
.initialShift = top,
});
}).translated(0, -top);
p.translate(0, top);
while (top < drawToY) {
const auto height = view->height();
@ -704,8 +701,7 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
}
}
top += height;
context.viewport.translate(0, -height);
context.clip.translate(0, -height);
context.translate(0, -height);
p.translate(0, height);
++iItem;

View File

@ -198,6 +198,22 @@ struct PaintContext {
QRect clip;
TextSelection selection;
crl::time now = 0;
void translate(int x, int y) {
viewport.translate(x, y);
clip.translate(x, y);
}
void translate(QPoint point) {
translate(point.x(), point.y());
}
[[nodiscard]] PaintContext translated(int x, int y) const {
auto result = *this;
result.translate(x, y);
return result;
}
[[nodiscard]] PaintContext translated(QPoint point) const {
return translated(point.x(), point.y());
}
};
class Element

View File

@ -594,25 +594,22 @@ void Message::draw(Painter &p, const PaintContext &context) const {
auto mediaTop = (trect.y() + trect.height() - mediaHeight);
p.translate(mediaLeft, mediaTop);
media->draw(
p,
context.clip.translated(-mediaLeft, -mediaTop),
skipTextSelection(context.selection), context.now);
auto mediaContext = context.translated(-mediaLeft, -mediaTop);
mediaContext.selection = skipTextSelection(context.selection);
media->draw(p, mediaContext);
p.translate(-mediaLeft, -mediaTop);
}
if (entry) {
auto entryLeft = inner.left();
auto entryTop = trect.y() + trect.height();
p.translate(entryLeft, entryTop);
auto entrySelection = skipTextSelection(context.selection);
auto entryContext = context.translated(-entryLeft, -entryTop);
entryContext.selection = skipTextSelection(context.selection);
if (mediaDisplayed) {
entrySelection = media->skipSelection(entrySelection);
entryContext.selection = media->skipSelection(
entryContext.selection);
}
entry->draw(
p,
context.clip.translated(-entryLeft, -entryTop),
entrySelection,
context.now);
entry->draw(p, entryContext);
p.translate(-entryLeft, -entryTop);
}
const auto needDrawInfo = entry
@ -652,11 +649,9 @@ void Message::draw(Painter &p, const PaintContext &context) const {
}
} else if (media && media->isDisplayed()) {
p.translate(g.topLeft());
media->draw(
p,
context.clip.translated(-g.topLeft()),
skipTextSelection(context.selection),
context.now);
auto mediaContext = context.translated(-g.topLeft());
mediaContext.selection = skipTextSelection(context.selection);
media->draw(p, mediaContext);
p.translate(-g.topLeft());
}

View File

@ -561,7 +561,9 @@ void Service::draw(Painter &p, const PaintContext &context) const {
height -= st::msgServiceMargin.top() + media->height();
auto left = st::msgServiceMargin.left() + (g.width() - media->maxWidth()) / 2, top = st::msgServiceMargin.top() + height + st::msgServiceMargin.top();
p.translate(left, top);
media->draw(p, clip.translated(-left, -top), TextSelection(), context.now);
auto mediaContext = context.translated(-left, -top);
mediaContext.selection = TextSelection();
media->draw(p, mediaContext);
p.translate(-left, -top);
}

View File

@ -72,12 +72,12 @@ QSize Call::countOptimalSize() {
return { maxWidth, minHeight };
}
void Call::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const {
void Call::draw(Painter &p, const PaintContext &context) const {
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) return;
auto paintw = width();
auto outbg = _parent->hasOutLayout();
auto selected = (selection == FullSelection);
auto selected = (context.selection == FullSelection);
accumulate_min(paintw, maxWidth());

View File

@ -22,7 +22,7 @@ public:
not_null<Element*> parent,
not_null<Data::Call*> call);
void draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const override;
void draw(Painter &p, const PaintContext &context) const override;
TextState textState(QPoint point, StateRequest request) const override;
bool toggleSelectionByHandlerClick(const ClickHandlerPtr &p) const override {

View File

@ -153,12 +153,12 @@ QSize Contact::countOptimalSize() {
return { maxWidth, minHeight };
}
void Contact::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const {
void Contact::draw(Painter &p, const PaintContext &context) const {
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) return;
auto paintw = width();
auto outbg = _parent->hasOutLayout();
bool selected = (selection == FullSelection);
bool selected = (context.selection == FullSelection);
accumulate_min(paintw, maxWidth());

View File

@ -29,7 +29,7 @@ public:
const QString &phone);
~Contact();
void draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const override;
void draw(Painter &p, const PaintContext &context) const override;
TextState textState(QPoint point, StateRequest request) const override;
bool toggleSelectionByHandlerClick(const ClickHandlerPtr &p) const override {

View File

@ -19,6 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/image/image.h"
#include "ui/text/format_values.h"
#include "ui/text/format_song_document_name.h"
#include "ui/chat/message_bubble.h"
#include "ui/cached_round_corners.h"
#include "ui/ui_utility.h"
#include "layout/layout_selection.h" // FullSelection
@ -325,19 +326,14 @@ QSize Document::countCurrentSize(int newWidth) {
return { newWidth, newHeight };
}
void Document::draw(
Painter &p,
const QRect &r,
TextSelection selection,
crl::time ms) const {
draw(p, width(), selection, ms, LayoutMode::Full);
void Document::draw(Painter &p, const PaintContext &context) const {
draw(p, width(), context, LayoutMode::Full);
}
void Document::draw(
Painter &p,
int width,
TextSelection selection,
crl::time ms,
const PaintContext &context,
LayoutMode mode) const {
if (width < st::msgPadding.left() + st::msgPadding.right() + 1) return;
@ -349,7 +345,7 @@ void Document::draw(
_dataMedia->automaticLoad(_realParent->fullId(), _realParent);
}
bool loaded = dataLoaded(), displayLoading = _data->displayLoading();
bool selected = (selection == FullSelection);
bool selected = (context.selection == FullSelection);
int captionw = width - st::msgPadding.left() - st::msgPadding.right();
auto outbg = _parent->hasOutLayout();
@ -507,19 +503,33 @@ void Document::draw(
}
return nullptr;
}();
if (previous && radialOpacity > 0. && radialOpacity < 1.) {
PaintInterpolatedIcon(p, *icon, *previous, radialOpacity, inner);
const auto paintContent = [&](Painter &q) {
if (previous && radialOpacity > 0. && radialOpacity < 1.) {
PaintInterpolatedIcon(q, *icon, *previous, radialOpacity, inner);
} else {
icon->paintInCenter(q, inner);
}
if (radial && !cornerDownload) {
QRect rinner(inner.marginsRemoved(QMargins(st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine)));
auto fg = outbg ? (selected ? st::historyFileOutRadialFgSelected : st::historyFileOutRadialFg) : (selected ? st::historyFileInRadialFgSelected : st::historyFileInRadialFg);
_animation->radial.draw(q, rinner, st::msgFileRadialLine, fg);
}
};
if (_data->isSongWithCover() || !usesBubblePattern(context)) {
paintContent(p);
} else {
icon->paintInCenter(p, inner);
Ui::PaintPatternBubblePart(
p,
context.viewport,
context.bubblesPattern->pixmap,
inner,
paintContent,
_iconCache);
}
if (radial && !cornerDownload) {
QRect rinner(inner.marginsRemoved(QMargins(st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine)));
auto fg = outbg ? (selected ? st::historyFileOutRadialFgSelected : st::historyFileOutRadialFg) : (selected ? st::historyFileInRadialFgSelected : st::historyFileInRadialFg);
_animation->radial.draw(p, rinner, st::msgFileRadialLine, fg);
}
drawCornerDownload(p, selected, mode);
drawCornerDownload(p, context, mode);
}
auto namewidth = width - nameleft - nameright;
auto statuswidth = namewidth;
@ -595,7 +605,7 @@ void Document::draw(
if (auto captioned = Get<HistoryDocumentCaptioned>()) {
p.setPen(outbg ? (selected ? st::historyTextOutFgSelected : st::historyTextOutFg) : (selected ? st::historyTextInFgSelected : st::historyTextInFg));
captioned->_caption.draw(p, st::msgPadding.left(), bottom, captionw, style::al_left, 0, -1, selection);
captioned->_caption.draw(p, st::msgPadding.left(), bottom, captionw, style::al_left, 0, -1, context.selection);
}
}
@ -625,7 +635,10 @@ bool Document::downloadInCorner() const {
&& IsServerMsgId(_realParent->id);
}
void Document::drawCornerDownload(Painter &p, bool selected, LayoutMode mode) const {
void Document::drawCornerDownload(
Painter &p,
const PaintContext &context,
LayoutMode mode) const {
if (dataLoaded()
|| _data->loadedInMediaCache()
|| !downloadInCorner()) {
@ -633,6 +646,7 @@ void Document::drawCornerDownload(Painter &p, bool selected, LayoutMode mode) co
}
auto outbg = _parent->hasOutLayout();
auto topMinus = isBubbleTop() ? 0 : st::msgFileTopMinus;
const auto selected = (context.selection == FullSelection);
const auto thumbed = false;
const auto &st = (mode == LayoutMode::Full)
? (thumbed ? st::msgFileThumbLayout : st::msgFileLayout)
@ -640,11 +654,16 @@ void Document::drawCornerDownload(Painter &p, bool selected, LayoutMode mode) co
const auto shift = st::historyAudioDownloadShift;
const auto size = st::historyAudioDownloadSize;
const auto inner = style::rtlrect(st.padding.left() + shift, st.padding.top() - topMinus + shift, size, size, width());
auto pen = (selected
? (outbg ? st::msgOutBgSelected : st::msgInBgSelected)
: (outbg ? st::msgOutBg : st::msgInBg))->p;
pen.setWidth(st::lineWidth);
p.setPen(pen);
const auto bubblePattern = usesBubblePattern(context);
if (bubblePattern) {
p.setPen(Qt::NoPen);
} else {
auto pen = (selected
? (outbg ? st::msgOutBgSelected : st::msgInBgSelected)
: (outbg ? st::msgOutBg : st::msgInBg))->p;
pen.setWidth(st::lineWidth);
p.setPen(pen);
}
if (selected) {
p.setBrush(outbg ? st::msgFileOutBgSelected : st::msgFileInBgSelected);
} else {
@ -660,11 +679,34 @@ void Document::drawCornerDownload(Painter &p, bool selected, LayoutMode mode) co
}
return &(outbg ? (selected ? st::historyAudioOutDownloadSelected : st::historyAudioOutDownload) : (selected ? st::historyAudioInDownloadSelected : st::historyAudioInDownload));
}();
icon->paintInCenter(p, inner);
if (_animation && _animation->radial.animating()) {
const auto rinner = inner.marginsRemoved(QMargins(st::historyAudioRadialLine, st::historyAudioRadialLine, st::historyAudioRadialLine, st::historyAudioRadialLine));
auto fg = outbg ? (selected ? st::historyFileOutRadialFgSelected : st::historyFileOutRadialFg) : (selected ? st::historyFileInRadialFgSelected : st::historyFileInRadialFg);
_animation->radial.draw(p, rinner, st::historyAudioRadialLine, fg);
const auto paintContent = [&](Painter &q) {
if (bubblePattern) {
auto hq = PainterHighQualityEnabler(q);
auto pen = st::msgOutBg->p;
pen.setWidth(st::lineWidth);
q.setPen(pen);
q.setBrush(Qt::NoBrush);
q.drawEllipse(inner);
}
icon->paintInCenter(q, inner);
if (_animation && _animation->radial.animating()) {
const auto rinner = inner.marginsRemoved(QMargins(st::historyAudioRadialLine, st::historyAudioRadialLine, st::historyAudioRadialLine, st::historyAudioRadialLine));
auto fg = outbg ? (selected ? st::historyFileOutRadialFgSelected : st::historyFileOutRadialFg) : (selected ? st::historyFileInRadialFgSelected : st::historyFileInRadialFg);
_animation->radial.draw(q, rinner, st::historyAudioRadialLine, fg);
}
};
if (bubblePattern) {
const auto add = st::lineWidth * 2;
const auto target = inner.marginsAdded({ add, add, add, add });
Ui::PaintPatternBubblePart(
p,
context.viewport,
context.bubblesPattern->pixmap,
target,
paintContent,
_cornerDownloadCache);
} else {
paintContent(p);
}
}
@ -978,9 +1020,7 @@ QSize Document::sizeForGrouping(int width) const {
void Document::drawGrouped(
Painter &p,
const QRect &clip,
TextSelection selection,
crl::time ms,
const PaintContext &context,
const QRect &geometry,
RectParts sides,
RectParts corners,
@ -991,8 +1031,7 @@ void Document::drawGrouped(
draw(
p,
geometry.width(),
selection,
ms,
context.translated(-geometry.topLeft()),
LayoutMode::Grouped);
p.translate(-geometry.topLeft());
}

View File

@ -34,7 +34,7 @@ public:
not_null<DocumentData*> document);
~Document();
void draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const override;
void draw(Painter &p, const PaintContext &context) const override;
TextState textState(QPoint point, StateRequest request) const override;
void updatePressed(QPoint point) override;
@ -65,9 +65,7 @@ public:
QSize sizeForGrouping(int width) const override;
void drawGrouped(
Painter &p,
const QRect &clip,
TextSelection selection,
crl::time ms,
const PaintContext &context,
const QRect &geometry,
RectParts sides,
RectParts corners,
@ -109,8 +107,7 @@ private:
void draw(
Painter &p,
int width,
TextSelection selection,
crl::time ms,
const PaintContext &context,
LayoutMode mode) const;
[[nodiscard]] TextState textState(
QPoint point,
@ -131,7 +128,10 @@ private:
bool updateStatusText() const; // returns showPause
[[nodiscard]] bool downloadInCorner() const;
void drawCornerDownload(Painter &p, bool selected, LayoutMode mode) const;
void drawCornerDownload(
Painter &p,
const PaintContext &context,
LayoutMode mode) const;
[[nodiscard]] TextState cornerDownloadTextState(
QPoint point,
StateRequest request,
@ -139,6 +139,8 @@ private:
not_null<DocumentData*> _data;
mutable std::shared_ptr<Data::DocumentMedia> _dataMedia;
mutable QImage _iconCache;
mutable QImage _cornerDownloadCache;
};

View File

@ -198,12 +198,12 @@ TextSelection Game::fromDescriptionSelection(
return ShiftItemSelection(selection, _title);
}
void Game::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const {
void Game::draw(Painter &p, const PaintContext &context) const {
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) return;
auto paintw = width();
auto outbg = _parent->hasOutLayout();
bool selected = (selection == FullSelection);
bool selected = (context.selection == FullSelection);
auto &barfg = selected ? (outbg ? st::msgOutReplyBarSelColor : st::msgInReplyBarSelColor) : (outbg ? st::msgOutReplyBarColor : st::msgInReplyBarColor);
auto &semibold = selected ? (outbg ? st::msgOutServiceFgSelected : st::msgInServiceFgSelected) : (outbg ? st::msgOutServiceFg : st::msgInServiceFg);
@ -227,7 +227,7 @@ void Game::draw(Painter &p, const QRect &r, TextSelection selection, crl::time m
if (_title.hasSkipBlock()) {
endskip = _parent->skipBlockWidth();
}
_title.drawLeftElided(p, padding.left(), tshift, paintw, width(), _titleLines, style::al_left, 0, -1, endskip, false, selection);
_title.drawLeftElided(p, padding.left(), tshift, paintw, width(), _titleLines, style::al_left, 0, -1, endskip, false, context.selection);
tshift += _titleLines * lineHeight;
}
if (_descriptionLines) {
@ -236,7 +236,7 @@ void Game::draw(Painter &p, const QRect &r, TextSelection selection, crl::time m
if (_description.hasSkipBlock()) {
endskip = _parent->skipBlockWidth();
}
_description.drawLeftElided(p, padding.left(), tshift, paintw, width(), _descriptionLines, style::al_left, 0, -1, endskip, false, toDescriptionSelection(selection));
_description.drawLeftElided(p, padding.left(), tshift, paintw, width(), _descriptionLines, style::al_left, 0, -1, endskip, false, toDescriptionSelection(context.selection));
tshift += _descriptionLines * lineHeight;
}
if (_attach) {
@ -247,10 +247,11 @@ void Game::draw(Painter &p, const QRect &r, TextSelection selection, crl::time m
auto attachTop = tshift - bubble.top();
if (rtl()) attachLeft = width() - attachLeft - _attach->width();
auto attachSelection = selected ? FullSelection : TextSelection { 0, 0 };
auto attachContext = context.translated(-attachLeft, -attachTop);
attachContext.selection = selected ? FullSelection : TextSelection { 0, 0 };
p.translate(attachLeft, attachTop);
_attach->draw(p, r.translated(-attachLeft, -attachTop), attachSelection, ms);
_attach->draw(p, attachContext);
auto pixwidth = _attach->width();
auto pixheight = _attach->height();

View File

@ -22,7 +22,7 @@ public:
void refreshParentId(not_null<HistoryItem*> realParent) override;
void draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const override;
void draw(Painter &p, const PaintContext &context) const override;
TextState textState(QPoint point, StateRequest request) const override;
[[nodiscard]] TextSelection adjustSelection(

View File

@ -276,14 +276,14 @@ bool Gif::autoplayEnabled() const {
_data);
}
void Gif::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const {
void Gif::draw(Painter &p, const PaintContext &context) const {
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) return;
ensureDataMediaCreated();
const auto item = _parent->data();
const auto loaded = dataLoaded();
const auto displayLoading = item->isSending() || _data->displayLoading();
const auto selected = (selection == FullSelection);
const auto selected = (context.selection == FullSelection);
const auto autoPaused = _parent->delegate()->elementIsGifPaused();
const auto cornerDownload = downloadInCorner();
const auto canBePlayed = _dataMedia->canBePlayed();
@ -613,7 +613,7 @@ void Gif::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms
}
if (!isRound && !_caption.isEmpty()) {
p.setPen(outbg ? (selected ? st::historyTextOutFgSelected : st::historyTextOutFg) : (selected ? st::historyTextInFgSelected : st::historyTextInFg));
_caption.draw(p, st::msgPadding.left(), painty + painth + st::mediaCaptionSkip, captionw, style::al_left, 0, -1, selection);
_caption.draw(p, st::msgPadding.left(), painty + painth + st::mediaCaptionSkip, captionw, style::al_left, 0, -1, context.selection);
} else if (!inWebPage) {
auto fullRight = paintx + usex + usew;
auto fullBottom = painty + painth;
@ -896,9 +896,7 @@ QSize Gif::sizeForGrouping(int width) const {
void Gif::drawGrouped(
Painter &p,
const QRect &clip,
TextSelection selection,
crl::time ms,
const PaintContext &context,
const QRect &geometry,
RectParts sides,
RectParts corners,
@ -909,7 +907,7 @@ void Gif::drawGrouped(
const auto item = _parent->data();
const auto loaded = dataLoaded();
const auto displayLoading = (item->id < 0) || _data->displayLoading();
const auto selected = (selection == FullSelection);
const auto selected = (context.selection == FullSelection);
const auto autoPaused = _parent->delegate()->elementIsGifPaused();
const auto fullFeatured = fullFeaturedGrouped(sides);
const auto cornerDownload = fullFeatured && downloadInCorner();

View File

@ -45,7 +45,7 @@ public:
not_null<DocumentData*> document);
~Gif();
void draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const override;
void draw(Painter &p, const PaintContext &context) const override;
TextState textState(QPoint point, StateRequest request) const override;
[[nodiscard]] TextSelection adjustSelection(
@ -73,9 +73,7 @@ public:
QSize sizeForGrouping(int width) const override;
void drawGrouped(
Painter &p,
const QRect &clip,
TextSelection selection,
crl::time ms,
const PaintContext &context,
const QRect &geometry,
RectParts sides,
RectParts corners,

View File

@ -199,12 +199,12 @@ void Invoice::refreshParentId(not_null<HistoryItem*> realParent) {
}
}
void Invoice::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const {
void Invoice::draw(Painter &p, const PaintContext &context) const {
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) return;
auto paintw = width();
auto outbg = _parent->hasOutLayout();
bool selected = (selection == FullSelection);
bool selected = (context.selection == FullSelection);
auto &semibold = selected ? (outbg ? st::msgOutServiceFgSelected : st::msgInServiceFgSelected) : (outbg ? st::msgOutServiceFg : st::msgInServiceFg);
@ -226,14 +226,14 @@ void Invoice::draw(Painter &p, const QRect &r, TextSelection selection, crl::tim
if (_title.hasSkipBlock()) {
endskip = _parent->skipBlockWidth();
}
_title.drawLeftElided(p, padding.left(), tshift, paintw, width(), _titleHeight / lineHeight, style::al_left, 0, -1, endskip, false, selection);
_title.drawLeftElided(p, padding.left(), tshift, paintw, width(), _titleHeight / lineHeight, style::al_left, 0, -1, endskip, false, context.selection);
tshift += _titleHeight;
p.setTextPalette(selected ? (outbg ? st::outTextPaletteSelected : st::inTextPaletteSelected) : (outbg ? st::outTextPalette : st::inTextPalette));
}
if (_descriptionHeight) {
p.setPen(outbg ? st::webPageDescriptionOutFg : st::webPageDescriptionInFg);
_description.drawLeft(p, padding.left(), tshift, paintw, width(), style::al_left, 0, -1, toDescriptionSelection(selection));
_description.drawLeft(p, padding.left(), tshift, paintw, width(), style::al_left, 0, -1, toDescriptionSelection(context.selection));
tshift += _descriptionHeight;
}
if (_attach) {
@ -244,10 +244,11 @@ void Invoice::draw(Painter &p, const QRect &r, TextSelection selection, crl::tim
auto attachTop = tshift - bubble.top();
if (rtl()) attachLeft = width() - attachLeft - _attach->width();
auto attachSelection = selected ? FullSelection : TextSelection { 0, 0 };
auto attachContext = context.translated(-attachLeft, -attachTop);
attachContext.selection = selected ? FullSelection : TextSelection { 0, 0 };
p.translate(attachLeft, attachTop);
_attach->draw(p, r.translated(-attachLeft, -attachTop), attachSelection, ms);
_attach->draw(p, attachContext);
auto pixwidth = _attach->width();
auto available = _status.maxWidth();

View File

@ -34,7 +34,7 @@ public:
return false;
}
void draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const override;
void draw(Painter &p, const PaintContext &context) const override;
TextState textState(QPoint point, StateRequest request) const override;
[[nodiscard]] TextSelection adjustSelection(

View File

@ -148,12 +148,12 @@ TextSelection Location::fromDescriptionSelection(
return ShiftItemSelection(selection, _title);
}
void Location::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const {
void Location::draw(Painter &p, const PaintContext &context) const {
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) return;
auto paintx = 0, painty = 0, paintw = width(), painth = height();
bool bubble = _parent->hasBubble();
auto outbg = _parent->hasOutLayout();
bool selected = (selection == FullSelection);
bool selected = (context.selection == FullSelection);
if (bubble) {
if (!_title.isEmpty() || !_description.isEmpty()) {
@ -166,12 +166,12 @@ void Location::draw(Painter &p, const QRect &r, TextSelection selection, crl::ti
if (!_title.isEmpty()) {
p.setPen(outbg ? st::webPageTitleOutFg : st::webPageTitleInFg);
_title.drawLeftElided(p, paintx + st::msgPadding.left(), painty, textw, width(), 2, style::al_left, 0, -1, 0, false, selection);
_title.drawLeftElided(p, paintx + st::msgPadding.left(), painty, textw, width(), 2, style::al_left, 0, -1, 0, false, context.selection);
painty += qMin(_title.countHeight(textw), 2 * st::webPageTitleFont->height);
}
if (!_description.isEmpty()) {
p.setPen(outbg ? st::webPageDescriptionOutFg : st::webPageDescriptionInFg);
_description.drawLeftElided(p, paintx + st::msgPadding.left(), painty, textw, width(), 3, style::al_left, 0, -1, 0, false, toDescriptionSelection(selection));
_description.drawLeftElided(p, paintx + st::msgPadding.left(), painty, textw, width(), 3, style::al_left, 0, -1, 0, false, toDescriptionSelection(context.selection));
painty += qMin(_description.countHeight(textw), 3 * st::webPageDescriptionFont->height);
}
if (!_title.isEmpty() || !_description.isEmpty()) {

View File

@ -27,7 +27,7 @@ public:
const QString &description = QString());
~Location();
void draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const override;
void draw(Painter &p, const PaintContext &context) const override;
TextState textState(QPoint point, StateRequest request) const override;
[[nodiscard]] TextSelection adjustSelection(

View File

@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/view/history_view_cursor_state.h"
#include "lottie/lottie_single_player.h"
#include "storage/storage_shared_media.h"
#include "layout/layout_selection.h"
#include "data/data_document.h"
#include "ui/item_text_options.h"
#include "ui/chat/message_bubble.h"
@ -173,6 +174,13 @@ auto Media::getBubbleSelectionIntervals(
return {};
}
bool Media::usesBubblePattern(const PaintContext &context) const {
return (context.selection != FullSelection)
&& _parent->hasOutLayout()
&& context.bubblesPattern
&& !context.viewport.isEmpty()
&& !context.bubblesPattern->pixmap.size().isEmpty();
}
PointState Media::pointState(QPoint point) const {
return QRect(0, 0, width(), height()).contains(point)

View File

@ -40,6 +40,7 @@ enum class CursorState : char;
enum class InfoDisplayType : char;
struct TextState;
struct StateRequest;
struct PaintContext;
class Element;
enum class MediaInBubbleState {
@ -85,11 +86,7 @@ public:
}
virtual void drawHighlight(Painter &p, int top) const {
}
virtual void draw(
Painter &p,
const QRect &r,
TextSelection selection,
crl::time ms) const = 0;
virtual void draw(Painter &p, const PaintContext &context) const = 0;
[[nodiscard]] virtual PointState pointState(QPoint point) const;
[[nodiscard]] virtual TextState textState(
QPoint point,
@ -170,9 +167,7 @@ public:
}
virtual void drawGrouped(
Painter &p,
const QRect &clip,
TextSelection selection,
crl::time ms,
const PaintContext &context,
const QRect &geometry,
RectParts sides,
RectParts corners,
@ -299,6 +294,8 @@ protected:
virtual void playAnimation(bool autoplay) {
}
[[nodiscard]] bool usesBubblePattern(const PaintContext &context) const;
const not_null<Element*> _parent;
MediaInBubbleState _inBubbleState = MediaInBubbleState::None;

View File

@ -281,21 +281,19 @@ void GroupedMedia::drawHighlight(Painter &p, int top) const {
}
}
void GroupedMedia::draw(
Painter &p,
const QRect &clip,
TextSelection selection,
crl::time ms) const {
void GroupedMedia::draw(Painter &p, const PaintContext &context) const {
auto wasCache = false;
auto nowCache = false;
const auto groupPadding = groupedPadding();
auto selection = context.selection;
const auto fullSelection = (selection == FullSelection);
const auto textSelection = (_mode == Mode::Column)
&& !fullSelection
&& !IsSubGroupSelection(selection);
for (auto i = 0, count = int(_parts.size()); i != count; ++i) {
const auto &part = _parts[i];
const auto partSelection = fullSelection
auto partContext = context;
partContext.selection = fullSelection
? FullSelection
: textSelection
? selection
@ -313,9 +311,7 @@ void GroupedMedia::draw(
}
part.content->drawGrouped(
p,
clip,
partSelection,
ms,
partContext,
part.geometry.translated(0, groupPadding.top()),
part.sides,
cornersFromSides(part.sides),

View File

@ -32,11 +32,7 @@ public:
void refreshParentId(not_null<HistoryItem*> realParent) override;
void drawHighlight(Painter &p, int top) const override;
void draw(
Painter &p,
const QRect &clip,
TextSelection selection,
crl::time ms) const override;
void draw(Painter &p, const PaintContext &context) const override;
PointState pointState(QPoint point) const override;
TextState textState(
QPoint point,

View File

@ -105,15 +105,11 @@ QSize UnwrappedMedia::countCurrentSize(int newWidth) {
return { newWidth, newHeight };
}
void UnwrappedMedia::draw(
Painter &p,
const QRect &r,
TextSelection selection,
crl::time ms) const {
void UnwrappedMedia::draw(Painter &p, const PaintContext &context) const {
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) {
return;
}
bool selected = (selection == FullSelection);
bool selected = (context.selection == FullSelection);
const auto rightAligned = _parent->hasOutLayout()
&& !_parent->delegate()->elementIsChatWide();

View File

@ -57,7 +57,7 @@ public:
not_null<Element*> parent,
std::unique_ptr<Content> content);
void draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const override;
void draw(Painter &p, const PaintContext &context) const override;
PointState pointState(QPoint point) const override;
TextState textState(QPoint point, StateRequest request) const override;

View File

@ -223,12 +223,12 @@ QSize Photo::countCurrentSize(int newWidth) {
return { newWidth, newHeight };
}
void Photo::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const {
void Photo::draw(Painter &p, const PaintContext &context) const {
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) return;
ensureDataMediaCreated();
_dataMedia->automaticLoad(_realParent->fullId(), _parent->data());
auto selected = (selection == FullSelection);
auto selected = (context.selection == FullSelection);
auto loaded = _dataMedia->loaded();
auto displayLoading = _data->displayLoading();
@ -330,7 +330,7 @@ void Photo::draw(Painter &p, const QRect &r, TextSelection selection, crl::time
if (!_caption.isEmpty()) {
auto outbg = _parent->hasOutLayout();
p.setPen(outbg ? (selected ? st::historyTextOutFgSelected : st::historyTextOutFg) : (selected ? st::historyTextInFgSelected : st::historyTextInFg));
_caption.draw(p, st::msgPadding.left(), painty + painth + st::mediaCaptionSkip, captionw, style::al_left, 0, -1, selection);
_caption.draw(p, st::msgPadding.left(), painty + painth + st::mediaCaptionSkip, captionw, style::al_left, 0, -1, context.selection);
} else if (!inWebPage) {
auto fullRight = paintx + paintw;
auto fullBottom = painty + painth;
@ -489,9 +489,7 @@ QSize Photo::sizeForGrouping(int width) const {
void Photo::drawGrouped(
Painter &p,
const QRect &clip,
TextSelection selection,
crl::time ms,
const PaintContext &context,
const QRect &geometry,
RectParts sides,
RectParts corners,
@ -503,7 +501,7 @@ void Photo::drawGrouped(
validateGroupedCache(geometry, corners, cacheKey, cache);
const auto selected = (selection == FullSelection);
const auto selected = (context.selection == FullSelection);
const auto loaded = _dataMedia->loaded();
const auto displayLoading = _data->displayLoading();
const auto bubble = _parent->hasBubble();

View File

@ -37,7 +37,7 @@ public:
int width);
~Photo();
void draw(Painter &p, const QRect &clip, TextSelection selection, crl::time ms) const override;
void draw(Painter &p, const PaintContext &context) const override;
TextState textState(QPoint point, StateRequest request) const override;
[[nodiscard]] TextSelection adjustSelection(
@ -62,9 +62,7 @@ public:
QSize sizeForGrouping(int width) const override;
void drawGrouped(
Painter &p,
const QRect &clip,
TextSelection selection,
crl::time ms,
const PaintContext &context,
const QRect &geometry,
RectParts sides,
RectParts corners,

View File

@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/view/history_view_element.h"
#include "history/view/history_view_cursor_state.h"
#include "calls/calls_instance.h"
#include "ui/chat/message_bubble.h"
#include "ui/text/text_options.h"
#include "ui/text/text_utilities.h"
#include "ui/text/format_values.h"
@ -715,15 +716,15 @@ void Poll::updateAnswerVotes() {
}
}
void Poll::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const {
void Poll::draw(Painter &p, const PaintContext &context) const {
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) return;
auto paintw = width();
checkSendingAnimation();
_poll->checkResultsReload(_parent->data(), ms);
_poll->checkResultsReload(_parent->data(), context.now);
const auto outbg = _parent->hasOutLayout();
const auto selected = (selection == FullSelection);
const auto selected = (context.selection == FullSelection);
const auto &regular = selected ? (outbg ? st::msgOutDateFgSelected : st::msgInDateFgSelected) : (outbg ? st::msgOutDateFg : st::msgInDateFg);
const auto padding = st::msgPadding;
@ -734,14 +735,14 @@ void Poll::draw(Painter &p, const QRect &r, TextSelection selection, crl::time m
paintw -= padding.left() + padding.right();
p.setPen(outbg ? st::webPageTitleOutFg : st::webPageTitleInFg);
_question.drawLeft(p, padding.left(), tshift, paintw, width(), style::al_left, 0, -1, selection);
_question.drawLeft(p, padding.left(), tshift, paintw, width(), style::al_left, 0, -1, context.selection);
tshift += _question.countHeight(paintw) + st::historyPollSubtitleSkip;
p.setPen(regular);
_subtitle.drawLeftElided(p, padding.left(), tshift, paintw, width());
paintRecentVoters(p, padding.left() + _subtitle.maxWidth(), tshift, selection);
paintCloseByTimer(p, padding.left() + paintw, tshift, selection);
paintShowSolution(p, padding.left() + paintw, tshift, selection);
paintRecentVoters(p, padding.left() + _subtitle.maxWidth(), tshift, context);
paintCloseByTimer(p, padding.left() + paintw, tshift, context.selection);
paintShowSolution(p, padding.left() + paintw, tshift, context.selection);
tshift += st::msgDateFont->height + st::historyPollAnswersSkip;
const auto progress = _answersAnimation
@ -773,14 +774,14 @@ void Poll::draw(Painter &p, const QRect &r, TextSelection selection, crl::time m
tshift,
paintw,
width(),
selection);
context.selection);
tshift += height;
}
if (!inlineFooter()) {
paintBottom(p, padding.left(), tshift, paintw, selection);
paintBottom(p, padding.left(), tshift, paintw, context.selection);
} else if (!_totalVotesLabel.isEmpty()) {
tshift += st::msgPadding.bottom();
paintInlineFooter(p, padding.left(), tshift, paintw, selection);
paintInlineFooter(p, padding.left(), tshift, paintw, context.selection);
}
}
@ -864,7 +865,7 @@ void Poll::paintRecentVoters(
Painter &p,
int left,
int top,
TextSelection selection) const {
const PaintContext &context) const {
const auto count = int(_recentVoters.size());
if (!count) {
return;
@ -875,7 +876,7 @@ void Poll::paintRecentVoters(
auto y = top;
const auto size = st::historyPollRecentVoterSize;
const auto outbg = _parent->hasOutLayout();
const auto selected = (selection == FullSelection);
const auto selected = (context.selection == FullSelection);
auto pen = (selected
? (outbg ? st::msgOutBgSelected : st::msgInBgSelected)
: (outbg ? st::msgOutBg : st::msgInBg))->p;
@ -888,10 +889,26 @@ void Poll::paintRecentVoters(
if (!was && recent.userpic) {
created = true;
}
p.setPen(pen);
p.setBrush(Qt::NoBrush);
PainterHighQualityEnabler hq(p);
p.drawEllipse(x, y, size, size);
const auto paintContent = [&](Painter &p) {
p.setPen(pen);
p.setBrush(Qt::NoBrush);
PainterHighQualityEnabler hq(p);
p.drawEllipse(x, y, size, size);
};
if (usesBubblePattern(context)) {
const auto add = st::lineWidth * 2;
const auto target = QRect(x, y, size, size).marginsAdded(
{ add, add, add, add });
Ui::PaintPatternBubblePart(
p,
context.viewport,
context.bubblesPattern->pixmap,
target,
paintContent,
_userpicCircleCache);
} else {
paintContent(p);
}
x -= st::historyPollRecentVoterSkip;
}
if (created) {

View File

@ -30,7 +30,7 @@ public:
not_null<PollData*> poll);
~Poll();
void draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const override;
void draw(Painter &p, const PaintContext &context) const override;
TextState textState(QPoint point, StateRequest request) const override;
bool toggleSelectionByHandlerClick(const ClickHandlerPtr &p) const override {
@ -107,7 +107,7 @@ private:
Painter &p,
int left,
int top,
TextSelection selection) const;
const PaintContext &context) const;
void paintCloseByTimer(
Painter &p,
int right,
@ -213,6 +213,7 @@ private:
mutable std::unique_ptr<Ui::FireworksAnimation> _fireworksAnimation;
Ui::Animations::Simple _wrongAnswerAnimation;
mutable QPoint _lastLinkPoint;
mutable QImage _userpicCircleCache;
mutable std::unique_ptr<CloseInformation> _close;

View File

@ -150,7 +150,7 @@ QSize ThemeDocument::countCurrentSize(int newWidth) {
return { newWidth, newHeight };
}
void ThemeDocument::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const {
void ThemeDocument::draw(Painter &p, const PaintContext &context) const {
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) return;
ensureDataMediaCreated();
@ -158,7 +158,7 @@ void ThemeDocument::draw(Painter &p, const QRect &r, TextSelection selection, cr
if (_data) {
_dataMedia->automaticLoad(_realParent->fullId(), _parent->data());
}
auto selected = (selection == FullSelection);
auto selected = (context.selection == FullSelection);
auto loaded = dataLoaded();
auto displayLoading = _data && _data->displayLoading();

View File

@ -27,11 +27,7 @@ public:
const std::optional<Data::WallPaper> &params);
~ThemeDocument();
void draw(
Painter &p,
const QRect &clip,
TextSelection selection,
crl::time ms) const override;
void draw(Painter &p, const PaintContext &context) const override;
TextState textState(QPoint point, StateRequest request) const override;
DocumentData *getDocument() const override {

View File

@ -448,12 +448,12 @@ void WebPage::unloadHeavyPart() {
_photoMedia = nullptr;
}
void WebPage::draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const {
void WebPage::draw(Painter &p, const PaintContext &context) const {
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) return;
auto paintw = width();
auto outbg = _parent->hasOutLayout();
bool selected = (selection == FullSelection);
bool selected = (context.selection == FullSelection);
auto &barfg = selected ? (outbg ? st::msgOutReplyBarSelColor : st::msgInReplyBarSelColor) : (outbg ? st::msgOutReplyBarColor : st::msgInReplyBarColor);
auto &semibold = selected ? (outbg ? st::msgOutServiceFgSelected : st::msgInServiceFgSelected) : (outbg ? st::msgOutServiceFg : st::msgInServiceFg);
@ -512,7 +512,7 @@ void WebPage::draw(Painter &p, const QRect &r, TextSelection selection, crl::tim
if (_siteName.hasSkipBlock()) {
endskip = _parent->skipBlockWidth();
}
_siteName.drawLeftElided(p, padding.left(), tshift, paintw, width(), _siteNameLines, style::al_left, 0, -1, endskip, false, selection);
_siteName.drawLeftElided(p, padding.left(), tshift, paintw, width(), _siteNameLines, style::al_left, 0, -1, endskip, false, context.selection);
tshift += lineHeight;
}
if (_titleLines) {
@ -521,7 +521,7 @@ void WebPage::draw(Painter &p, const QRect &r, TextSelection selection, crl::tim
if (_title.hasSkipBlock()) {
endskip = _parent->skipBlockWidth();
}
_title.drawLeftElided(p, padding.left(), tshift, paintw, width(), _titleLines, style::al_left, 0, -1, endskip, false, toTitleSelection(selection));
_title.drawLeftElided(p, padding.left(), tshift, paintw, width(), _titleLines, style::al_left, 0, -1, endskip, false, toTitleSelection(context.selection));
tshift += _titleLines * lineHeight;
}
if (_descriptionLines) {
@ -531,10 +531,10 @@ void WebPage::draw(Painter &p, const QRect &r, TextSelection selection, crl::tim
endskip = _parent->skipBlockWidth();
}
if (_descriptionLines > 0) {
_description.drawLeftElided(p, padding.left(), tshift, paintw, width(), _descriptionLines, style::al_left, 0, -1, endskip, false, toDescriptionSelection(selection));
_description.drawLeftElided(p, padding.left(), tshift, paintw, width(), _descriptionLines, style::al_left, 0, -1, endskip, false, toDescriptionSelection(context.selection));
tshift += _descriptionLines * lineHeight;
} else {
_description.drawLeft(p, padding.left(), tshift, paintw, width(), style::al_left, 0, -1, toDescriptionSelection(selection));
_description.drawLeft(p, padding.left(), tshift, paintw, width(), style::al_left, 0, -1, toDescriptionSelection(context.selection));
tshift += _description.countHeight(paintw);
}
}
@ -548,8 +548,9 @@ void WebPage::draw(Painter &p, const QRect &r, TextSelection selection, crl::tim
p.translate(attachLeft, attachTop);
auto attachSelection = selected ? FullSelection : TextSelection { 0, 0 };
_attach->draw(p, r.translated(-attachLeft, -attachTop), attachSelection, ms);
auto attachContext = context.translated(-attachLeft, -attachTop);
attachContext.selection = selected ? FullSelection : TextSelection { 0, 0 };
_attach->draw(p, attachContext);
auto pixwidth = _attach->width();
auto pixheight = _attach->height();

View File

@ -24,7 +24,7 @@ public:
void refreshParentId(not_null<HistoryItem*> realParent) override;
void draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const override;
void draw(Painter &p, const PaintContext &context) const override;
TextState textState(QPoint point, StateRequest request) const override;
bool hideMessageText() const override {

View File

@ -93,10 +93,11 @@ void PaintPatternBubble(Painter &p, const SimpleBubble &args) {
const auto fill = rect.intersected(args.patternViewport);
if (!fill.isEmpty()) {
p.setClipRect(fill);
// #TODO bubbles optimizes
const auto to = args.patternViewport;
const auto from = QRect(QPoint(), pattern->pixmap.size());
p.drawPixmap(to, pattern->pixmap, from);
PaintPatternBubblePart(
p,
args.patternViewport,
pattern->pixmap,
fill);
p.setClipping(false);
}
};
@ -112,26 +113,13 @@ void PaintPatternBubble(Painter &p, const SimpleBubble &args) {
int y,
const QImage &mask,
QImage &cache) {
Expects(mask.bytesPerLine() == mask.width() * 4);
Expects(mask.format() == QImage::Format_ARGB32_Premultiplied);
if (cache.size() != mask.size()) {
cache = QImage(
mask.size(),
QImage::Format_ARGB32_Premultiplied);
}
cache.setDevicePixelRatio(mask.devicePixelRatio());
Assert(cache.bytesPerLine() == cache.width() * 4);
memcpy(cache.bits(), mask.constBits(), mask.sizeInBytes());
auto q = QPainter(&cache);
q.setCompositionMode(QPainter::CompositionMode_SourceIn);
const auto to = args.patternViewport.translated(-x, -y);
const auto from = QRect(QPoint(), pattern->pixmap.size());
q.drawPixmap(to, pattern->pixmap, from);
q.end();
p.drawImage(x, y, cache);
PaintPatternBubblePart(
p,
args.patternViewport,
pattern->pixmap,
QRect(QPoint(x, y), mask.size() / int(mask.devicePixelRatio())),
mask,
cache);
};
const auto fillCorner = [&](int x, int y, int index) {
fillPattern(
@ -365,4 +353,72 @@ void PaintBubble(Painter &p, const ComplexBubble &args) {
}
}
void PaintPatternBubblePart(
QPainter &p,
const QRect &viewport,
const QPixmap &pixmap,
const QRect &target) {
// #TODO bubbles optimizes
const auto to = viewport;
const auto from = QRect(QPoint(), pixmap.size());
p.drawPixmap(to, pixmap, from);
}
void PaintPatternBubblePart(
QPainter &p,
const QRect &viewport,
const QPixmap &pixmap,
const QRect &target,
const QImage &mask,
QImage &cache) {
Expects(mask.bytesPerLine() == mask.width() * 4);
Expects(mask.format() == QImage::Format_ARGB32_Premultiplied);
if (cache.size() != mask.size()) {
cache = QImage(
mask.size(),
QImage::Format_ARGB32_Premultiplied);
}
cache.setDevicePixelRatio(mask.devicePixelRatio());
Assert(cache.bytesPerLine() == cache.width() * 4);
memcpy(cache.bits(), mask.constBits(), mask.sizeInBytes());
auto q = QPainter(&cache);
q.setCompositionMode(QPainter::CompositionMode_SourceIn);
PaintPatternBubblePart(
q,
viewport.translated(-target.topLeft()),
pixmap,
QRect(QPoint(), cache.size() / int(cache.devicePixelRatio())));
q.end();
p.drawImage(target, cache);
}
void PaintPatternBubblePart(
QPainter &p,
const QRect &viewport,
const QPixmap &pixmap,
const QRect &target,
Fn<void(Painter&)> paintContent,
QImage &cache) {
Expects(paintContent != nullptr);
if (cache.size() != target.size() * style::DevicePixelRatio()) {
cache = QImage(
target.size() * style::DevicePixelRatio(),
QImage::Format_ARGB32_Premultiplied);
cache.setDevicePixelRatio(style::DevicePixelRatio());
}
cache.fill(Qt::transparent);
auto q = Painter(&cache);
q.translate(-target.topLeft());
paintContent(q);
q.setCompositionMode(QPainter::CompositionMode_SourceIn);
PaintPatternBubblePart(q, viewport, pixmap, target);
q.end();
p.drawImage(target, cache);
}
} // namespace Ui

View File

@ -49,4 +49,26 @@ struct ComplexBubble {
void PaintBubble(Painter &p, const SimpleBubble &args);
void PaintBubble(Painter &p, const ComplexBubble &args);
void PaintPatternBubblePart(
QPainter &p,
const QRect &viewport,
const QPixmap &pixmap,
const QRect &target);
void PaintPatternBubblePart(
QPainter &p,
const QRect &viewport,
const QPixmap &pixmap,
const QRect &target,
const QImage &mask,
QImage &cache);
void PaintPatternBubblePart(
QPainter &p,
const QRect &viewport,
const QPixmap &pixmap,
const QRect &target,
Fn<void(Painter&)> paintContent,
QImage &cache);
} // namespace Ui

View File

@ -1484,8 +1484,8 @@ HistoryView::PaintContext SessionController::bubblesContext(
//}
return {
.bubblesPattern = _bubblesBackgroundPattern.get(),
.viewport = viewport.translated(0, -args.initialShift),
.clip = args.clip.translated(0, -args.initialShift),
.viewport = viewport,
.clip = args.clip,
.now = crl::now(),
};
}

View File

@ -454,7 +454,6 @@ public:
int visibleAreaTopGlobal = 0;
int visibleAreaWidth = 0;
QRect clip;
int initialShift = 0;
};
[[nodiscard]] HistoryView::PaintContext bubblesContext(
BubblesContextArgs &&args);