2
0
mirror of https://github.com/kotatogram/kotatogram-desktop synced 2025-08-31 14:45:14 +00:00

Allow arbitrary QImage as outgoing bubbles background.

This commit is contained in:
John Preston
2021-08-19 17:22:12 +03:00
parent 1cc9a52461
commit f4fdadd3b0
21 changed files with 677 additions and 232 deletions

View File

@@ -106,13 +106,12 @@ void SectionWidget::PaintBackground(
Painter p(widget);
const auto background = Window::Theme::Background();
const auto fullHeight = controller->content()->height();
if (const auto color = background->colorForFill()) {
p.fillRect(clip, *color);
return;
}
const auto gradient = background->gradientForFill();
const auto fill = QSize(widget->width(), fullHeight);
const auto fill = QSize(widget->width(), controller->content()->height());
auto fromy = controller->content()->backgroundFromY();
auto state = controller->backgroundState(fill);
const auto paintCache = [&](const CachedBackground &cache) {
@@ -150,7 +149,26 @@ void SectionWidget::PaintBackground(
return;
}
const auto &prepared = background->prepared();
if (!prepared.isNull() && !background->tile()) {
if (prepared.isNull()) {
return;
} else if (background->tile()) {
const auto &tiled = background->preparedForTiled();
const auto left = clip.left();
const auto top = clip.top();
const auto right = clip.left() + clip.width();
const auto bottom = clip.top() + clip.height();
const auto w = tiled.width() / cRetinaFactor();
const auto h = tiled.height() / cRetinaFactor();
const auto sx = qFloor(left / w);
const auto sy = qFloor((top - fromy) / h);
const auto cx = qCeil(right / w);
const auto cy = qCeil((bottom - fromy) / h);
for (auto i = sx; i < cx; ++i) {
for (auto j = sy; j < cy; ++j) {
p.drawImage(QPointF(i * w, fromy + j * h), tiled);
}
}
} else {
const auto hq = PainterHighQualityEnabler(p);
const auto rects = Window::Theme::ComputeBackgroundRects(
fill,
@@ -158,25 +176,6 @@ void SectionWidget::PaintBackground(
auto to = rects.to;
to.moveTop(to.top() + fromy);
p.drawImage(to, prepared, rects.from);
return;
}
if (!prepared.isNull()) {
const auto &tiled = background->preparedForTiled();
auto left = clip.left();
auto top = clip.top();
auto right = clip.left() + clip.width();
auto bottom = clip.top() + clip.height();
auto w = tiled.width() / cRetinaFactor();
auto h = tiled.height() / cRetinaFactor();
auto sx = qFloor(left / w);
auto sy = qFloor((top - fromy) / h);
auto cx = qCeil(right / w);
auto cy = qCeil((bottom - fromy) / h);
for (auto i = sx; i < cx; ++i) {
for (auto j = sy; j < cy; ++j) {
p.drawImage(QPointF(i * w, fromy + j * h), tiled);
}
}
}
}

View File

@@ -42,6 +42,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/layers/generic_box.h"
#include "ui/text/text_utilities.h"
#include "ui/delayed_activation.h"
#include "ui/chat/message_bubble.h"
#include "ui/toast/toast.h"
#include "ui/toasts/common_toasts.h"
#include "calls/calls_instance.h" // Core::App().calls().inCall().
@@ -63,6 +64,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "styles/style_window.h"
#include "styles/style_dialogs.h"
#include "styles/style_layers.h" // st::boxLabel
#include "styles/style_chat.h" // st::historyMessageRadius
#include <QtGui/QGuiApplication>
@@ -1445,6 +1447,49 @@ void SessionController::openDocument(
session().data().message(contextId));
}
void SessionController::setBubblesBackground(QImage image) {
_bubblesBackgroundPrepared = std::move(image);
if (!_bubblesBackground.area.isEmpty()) {
_bubblesBackground = CacheBackground({
.prepared = _bubblesBackgroundPrepared,
.area = _bubblesBackground.area,
});
}
if (!_bubblesBackgroundPattern) {
_bubblesBackgroundPattern = Ui::PrepareBubblePattern();
}
_bubblesBackgroundPattern->pixmap = _bubblesBackground.pixmap;
_repaintBackgroundRequests.fire({});
}
HistoryView::PaintContext SessionController::bubblesContext(
BubblesContextArgs &&args) {
const auto visibleAreaTopLocal = content()->mapFromGlobal(
QPoint(0, args.visibleAreaTopGlobal)).y();
const auto viewport = QRect(
0,
args.visibleAreaTop - visibleAreaTopLocal,
args.visibleAreaWidth,
content()->height());
_bubblesBackground.area = viewport.size();
//if (!_bubblesBackgroundPrepared.isNull()
// && _bubblesBackground.area != viewport.size()
// && !viewport.isEmpty()) {
// // #TODO bubbles delayed caching
// _bubblesBackground = CacheBackground({
// .prepared = _bubblesBackgroundPrepared,
// .area = viewport.size(),
// });
// _bubblesBackgroundPattern->pixmap = _bubblesBackground.pixmap;
//}
return {
.bubblesPattern = _bubblesBackgroundPattern.get(),
.viewport = viewport.translated(0, -args.initialShift),
.clip = args.clip.translated(0, -args.initialShift),
.now = crl::now(),
};
}
const BackgroundState &SessionController::backgroundState(QSize area) {
_backgroundState.shown = _backgroundFade.value(1.);
if (_backgroundState.now.pixmap.isNull()
@@ -1580,7 +1625,8 @@ void SessionController::setCachedBackground(CacheBackgroundResult &&cached) {
const auto background = Window::Theme::Background();
if (background->gradientForFill().isNull()
|| _backgroundState.now.pixmap.isNull()) {
|| _backgroundState.now.pixmap.isNull()
|| anim::Disabled()) {
_backgroundFade.stop();
_backgroundState.shown = 1.;
_backgroundState.now = std::move(cached);

View File

@@ -26,6 +26,10 @@ namespace Adaptive {
enum class WindowLayout;
} // namespace Adaptive
namespace HistoryView {
struct PaintContext;
} // namespace HistoryView
namespace ChatHelpers {
class TabbedSelector;
} // namespace ChatHelpers
@@ -46,6 +50,7 @@ class FormController;
namespace Ui {
class LayerWidget;
enum class ReportReason;
struct BubblePattern;
} // namespace Ui
namespace Window {
@@ -439,6 +444,20 @@ public:
void toggleFiltersMenu(bool enabled);
[[nodiscard]] rpl::producer<> filtersMenuChanged() const;
void setBubblesBackground(QImage image);
const Ui::BubblePattern *bubblesBackgroundPattern() const {
return _bubblesBackgroundPattern.get();
}
struct BubblesContextArgs {
int visibleAreaTop = 0;
int visibleAreaTopGlobal = 0;
int visibleAreaWidth = 0;
QRect clip;
int initialShift = 0;
};
[[nodiscard]] HistoryView::PaintContext bubblesContext(
BubblesContextArgs &&args);
[[nodiscard]] const BackgroundState &backgroundState(QSize area);
[[nodiscard]] rpl::producer<> repaintBackgroundRequests() const;
void rotateComplexGradientBackground();
@@ -520,6 +539,10 @@ private:
QSize _willCacheForArea;
crl::time _lastAreaChangeTime = 0;
base::Timer _cacheBackgroundTimer;
CachedBackground _bubblesBackground;
QImage _bubblesBackgroundPrepared;
std::unique_ptr<Ui::BubblePattern> _bubblesBackgroundPattern;
rpl::event_stream<> _repaintBackgroundRequests;
rpl::lifetime _lifetime;