mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 14:17:12 +02:00
Don't blend SoftLight patterns in realtime.
This commit is contained in:
parent
2b46f87d7b
commit
b9a9520ef5
7 changed files with 92 additions and 59 deletions
|
@ -91,36 +91,61 @@ void SectionWidget::PaintBackground(
|
|||
Painter p(widget);
|
||||
|
||||
const auto background = Window::Theme::Background();
|
||||
auto fill = QRect(0, 0, widget->width(), controller->content()->height());
|
||||
const auto fullHeight = controller->content()->height();
|
||||
if (const auto color = background->colorForFill()) {
|
||||
p.fillRect(fill, *color);
|
||||
return;
|
||||
}
|
||||
auto fromy = controller->content()->backgroundFromY();
|
||||
auto cached = controller->cachedBackground(fill);
|
||||
if (!cached.pixmap.isNull()) {
|
||||
p.drawPixmap(cached.x, fromy + cached.y, cached.pixmap);
|
||||
p.fillRect(clip, *color);
|
||||
return;
|
||||
}
|
||||
const auto gradient = background->gradientForFill();
|
||||
const auto fill = QSize(widget->width(), fullHeight);
|
||||
auto fromy = controller->content()->backgroundFromY();
|
||||
auto cached = controller->cachedBackground(fill);
|
||||
const auto goodCache = (cached.area == fill);
|
||||
const auto useCached = goodCache || !gradient.isNull();
|
||||
if (!cached.pixmap.isNull()) {
|
||||
const auto to = QRect(
|
||||
QPoint(cached.x, fromy + cached.y),
|
||||
cached.pixmap.size() / cIntRetinaFactor());
|
||||
if (goodCache) {
|
||||
p.drawPixmap(to, cached.pixmap);
|
||||
} else {
|
||||
const auto sx = fill.width() / float64(cached.area.width());
|
||||
const auto sy = fill.height() / float64(cached.area.height());
|
||||
const auto round = [](float64 value) -> int {
|
||||
return (value >= 0.)
|
||||
? int(std::ceil(value))
|
||||
: int(std::floor(value));
|
||||
};
|
||||
const auto sto = QPoint(round(to.x() * sx), round(to.y() * sy));
|
||||
p.drawPixmap(
|
||||
sto.x(),
|
||||
sto.y(),
|
||||
round((to.x() + to.width()) * sx) - sto.x(),
|
||||
round((to.y() + to.height()) * sy) - sto.y(),
|
||||
cached.pixmap);
|
||||
}
|
||||
return;
|
||||
}
|
||||
const auto patternOpacity = background->paper().patternOpacity();
|
||||
const auto &bg = background->pixmap();
|
||||
if (!bg.isNull() && !background->tile()) {
|
||||
auto hq = PainterHighQualityEnabler(p);
|
||||
QRect to, from;
|
||||
Window::Theme::ComputeBackgroundRects(fill, bg.size(), to, from);
|
||||
const auto rects = Window::Theme::ComputeBackgroundRects(
|
||||
fill,
|
||||
bg.size());
|
||||
if (!gradient.isNull()) {
|
||||
p.drawImage(to, gradient);
|
||||
p.drawImage(rects.to, gradient);
|
||||
p.setCompositionMode(QPainter::CompositionMode_SoftLight);
|
||||
p.setOpacity(patternOpacity);
|
||||
}
|
||||
auto to = rects.to;
|
||||
to.moveTop(to.top() + fromy);
|
||||
p.drawPixmap(to, bg, from);
|
||||
p.drawPixmap(to, bg, rects.from);
|
||||
return;
|
||||
}
|
||||
if (!gradient.isNull()) {
|
||||
auto hq = PainterHighQualityEnabler(p);
|
||||
p.drawImage(fill, gradient);
|
||||
p.drawImage(QRect(QPoint(0, fromy), fill), gradient);
|
||||
p.setCompositionMode(QPainter::CompositionMode_SoftLight);
|
||||
p.setOpacity(patternOpacity);
|
||||
}
|
||||
|
|
|
@ -1494,27 +1494,31 @@ QImage PreprocessBackgroundImage(QImage image) {
|
|||
return image;
|
||||
}
|
||||
|
||||
void ComputeBackgroundRects(QRect wholeFill, QSize imageSize, QRect &to, QRect &from) {
|
||||
if (uint64(imageSize.width()) * wholeFill.height() > uint64(imageSize.height()) * wholeFill.width()) {
|
||||
float64 pxsize = wholeFill.height() / float64(imageSize.height());
|
||||
int takewidth = qCeil(wholeFill.width() / pxsize);
|
||||
BackgroundRects ComputeBackgroundRects(QSize fillSize, QSize imageSize) {
|
||||
if (uint64(imageSize.width()) * fillSize.height() > uint64(imageSize.height()) * fillSize.width()) {
|
||||
float64 pxsize = fillSize.height() / float64(imageSize.height());
|
||||
int takewidth = qCeil(fillSize.width() / pxsize);
|
||||
if (takewidth > imageSize.width()) {
|
||||
takewidth = imageSize.width();
|
||||
} else if ((imageSize.width() % 2) != (takewidth % 2)) {
|
||||
++takewidth;
|
||||
}
|
||||
to = QRect(int((wholeFill.width() - takewidth * pxsize) / 2.), 0, qCeil(takewidth * pxsize), wholeFill.height());
|
||||
from = QRect((imageSize.width() - takewidth) / 2, 0, takewidth, imageSize.height());
|
||||
return {
|
||||
.from = QRect((imageSize.width() - takewidth) / 2, 0, takewidth, imageSize.height()),
|
||||
.to = QRect(int((fillSize.width() - takewidth * pxsize) / 2.), 0, qCeil(takewidth * pxsize), fillSize.height()),
|
||||
};
|
||||
} else {
|
||||
float64 pxsize = wholeFill.width() / float64(imageSize.width());
|
||||
int takeheight = qCeil(wholeFill.height() / pxsize);
|
||||
float64 pxsize = fillSize.width() / float64(imageSize.width());
|
||||
int takeheight = qCeil(fillSize.height() / pxsize);
|
||||
if (takeheight > imageSize.height()) {
|
||||
takeheight = imageSize.height();
|
||||
} else if ((imageSize.height() % 2) != (takeheight % 2)) {
|
||||
++takeheight;
|
||||
}
|
||||
to = QRect(0, int((wholeFill.height() - takeheight * pxsize) / 2.), wholeFill.width(), qCeil(takeheight * pxsize));
|
||||
from = QRect(0, (imageSize.height() - takeheight) / 2, imageSize.width(), takeheight);
|
||||
return {
|
||||
.from = QRect(0, (imageSize.height() - takeheight) / 2, imageSize.width(), takeheight),
|
||||
.to = QRect(0, int((fillSize.height() - takeheight * pxsize) / 2.), fillSize.width(), qCeil(takeheight * pxsize)),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -270,7 +270,13 @@ private:
|
|||
|
||||
[[nodiscard]] ChatBackground *Background();
|
||||
|
||||
void ComputeBackgroundRects(QRect wholeFill, QSize imageSize, QRect &to, QRect &from);
|
||||
struct BackgroundRects {
|
||||
QRect from;
|
||||
QRect to;
|
||||
};
|
||||
[[nodiscard]] BackgroundRects ComputeBackgroundRects(
|
||||
QSize fillSize,
|
||||
QSize imageSize);
|
||||
|
||||
bool ReadPaletteValues(const QByteArray &content, Fn<bool(QLatin1String name, QLatin1String value)> callback);
|
||||
|
||||
|
|
|
@ -455,12 +455,12 @@ void Generator::paintHistoryBackground() {
|
|||
} else {
|
||||
PainterHighQualityEnabler hq(*_p);
|
||||
|
||||
auto fill = QRect(_topBar.x(), _topBar.y(), _topBar.width(), _body.height());
|
||||
QRect to, from;
|
||||
ComputeBackgroundRects(fill, background.size(), to, from);
|
||||
auto fill = QSize(_topBar.width(), _body.height());
|
||||
const auto rects = ComputeBackgroundRects(fill, background.size());
|
||||
auto to = rects.to;
|
||||
to.moveTop(to.top() + fromy);
|
||||
to.moveTopLeft(to.topLeft() + _history.topLeft());
|
||||
_p->drawImage(to, background, from);
|
||||
_p->drawImage(to, background, rects.from);
|
||||
}
|
||||
_p->setClipping(false);
|
||||
}
|
||||
|
|
|
@ -984,24 +984,24 @@ void MainMenu::refreshMenu() {
|
|||
}
|
||||
|
||||
void MainMenu::refreshBackground() {
|
||||
const auto fill = QRect(0, 0, st::mainMenuWidth, st::mainMenuCoverHeight);
|
||||
const auto fill = QSize(st::mainMenuWidth, st::mainMenuCoverHeight);
|
||||
const auto intensityText = IntensityOfColor(st::mainMenuCoverFg->c);
|
||||
const auto background = Window::Theme::Background();
|
||||
const auto &paper = background->paper();
|
||||
const auto &pixmap = background->pixmap();
|
||||
|
||||
QRect to, from;
|
||||
Window::Theme::ComputeBackgroundRects(fill, pixmap.size(), to, from);
|
||||
const auto rects = Window::Theme::ComputeBackgroundRects(fill, pixmap.size());
|
||||
|
||||
auto backgroundImage = !paper.backgroundColors().empty()
|
||||
? Data::GenerateWallPaper(
|
||||
fill.size() * cIntRetinaFactor(),
|
||||
fill * cIntRetinaFactor(),
|
||||
paper.backgroundColors(),
|
||||
paper.gradientRotation(),
|
||||
paper.patternOpacity(),
|
||||
[&](QPainter &p) { p.drawPixmap(to, pixmap, from); })
|
||||
: QImage(
|
||||
fill.size() * cIntRetinaFactor(),
|
||||
fill * cIntRetinaFactor(),
|
||||
QImage::Format_ARGB32_Premultiplied);
|
||||
QPainter p(&backgroundImage);
|
||||
|
||||
|
@ -1019,7 +1019,7 @@ void MainMenu::refreshBackground() {
|
|||
// Solid color.
|
||||
if (const auto color = background->colorForFill()) {
|
||||
const auto intensity = IntensityOfColor(*color);
|
||||
p.fillRect(fill, *color);
|
||||
p.fillRect(QRect(QPoint(), fill), *color);
|
||||
if (std::abs(intensity - intensityText) < kMinDiffIntensity) {
|
||||
drawShadow(p);
|
||||
}
|
||||
|
|
|
@ -1318,17 +1318,15 @@ void SessionController::openDocument(
|
|||
session().data().message(contextId));
|
||||
}
|
||||
|
||||
CachedBackground SessionController::cachedBackground(QRect area) {
|
||||
if (!_cachedBackground.pixmap.isNull()
|
||||
&& area == _cachedBackground.area) {
|
||||
return _cachedBackground;
|
||||
CachedBackground SessionController::cachedBackground(QSize area) {
|
||||
if (_cachedBackground.area != area) {
|
||||
if (_willCacheForArea != area || !_cacheBackgroundTimer.isActive()) {
|
||||
_willCacheForArea = area;
|
||||
_lastAreaChangeTime = crl::now();
|
||||
_cacheBackgroundTimer.callOnce(kCacheBackgroundFastTimeout);
|
||||
}
|
||||
}
|
||||
if (_willCacheForArea != area || !_cacheBackgroundTimer.isActive()) {
|
||||
_willCacheForArea = area;
|
||||
_lastAreaChangeTime = crl::now();
|
||||
_cacheBackgroundTimer.callOnce(kCacheBackgroundFastTimeout);
|
||||
}
|
||||
return {};
|
||||
return _cachedBackground;
|
||||
}
|
||||
|
||||
void SessionController::cacheBackground() {
|
||||
|
@ -1348,10 +1346,10 @@ void SessionController::cacheBackground() {
|
|||
if (background->tile() || bg.isNull()) {
|
||||
auto result = gradient.isNull()
|
||||
? QImage(
|
||||
_willCacheForArea.size() * cIntRetinaFactor(),
|
||||
_willCacheForArea * cIntRetinaFactor(),
|
||||
QImage::Format_ARGB32_Premultiplied)
|
||||
: gradient.scaled(
|
||||
_willCacheForArea.size() * cIntRetinaFactor(),
|
||||
_willCacheForArea * cIntRetinaFactor(),
|
||||
Qt::IgnoreAspectRatio,
|
||||
Qt::SmoothTransformation);
|
||||
result.setDevicePixelRatio(cRetinaFactor());
|
||||
|
@ -1379,15 +1377,12 @@ void SessionController::cacheBackground() {
|
|||
.area = _willCacheForArea,
|
||||
};
|
||||
} else {
|
||||
QRect to, from;
|
||||
Window::Theme::ComputeBackgroundRects(
|
||||
const auto rects = Window::Theme::ComputeBackgroundRects(
|
||||
_willCacheForArea,
|
||||
bg.size(),
|
||||
to,
|
||||
from);
|
||||
auto image = bg.toImage().copy(from).scaled(
|
||||
to.width() * cIntRetinaFactor(),
|
||||
to.height() * cIntRetinaFactor(),
|
||||
bg.size());
|
||||
auto image = bg.toImage().copy(rects.from).scaled(
|
||||
rects.to.width() * cIntRetinaFactor(),
|
||||
rects.to.height() * cIntRetinaFactor(),
|
||||
Qt::IgnoreAspectRatio,
|
||||
Qt::SmoothTransformation);
|
||||
auto result = gradient.isNull()
|
||||
|
@ -1401,16 +1396,19 @@ void SessionController::cacheBackground() {
|
|||
QPainter p(&result);
|
||||
p.setCompositionMode(QPainter::CompositionMode_SoftLight);
|
||||
p.setOpacity(patternOpacity);
|
||||
p.drawImage(QRect(QPoint(), to.size()), image);
|
||||
p.drawImage(QRect(QPoint(), rects.to.size()), image);
|
||||
}
|
||||
image = QImage();
|
||||
_cachedBackground = {
|
||||
.pixmap = Ui::PixmapFromImage(std::move(result)),
|
||||
.area = _willCacheForArea,
|
||||
.x = to.x(),
|
||||
.y = to.y(),
|
||||
.x = rects.to.x(),
|
||||
.y = rects.to.y(),
|
||||
};
|
||||
}
|
||||
if (!gradient.isNull()) {
|
||||
content()->update();
|
||||
}
|
||||
}
|
||||
|
||||
void SessionController::clearCachedBackground() {
|
||||
|
|
|
@ -58,7 +58,7 @@ class FiltersMenu;
|
|||
|
||||
struct CachedBackground {
|
||||
QPixmap pixmap;
|
||||
QRect area;
|
||||
QSize area;
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
};
|
||||
|
@ -400,7 +400,7 @@ public:
|
|||
void toggleFiltersMenu(bool enabled);
|
||||
[[nodiscard]] rpl::producer<> filtersMenuChanged() const;
|
||||
|
||||
[[nodiscard]] CachedBackground cachedBackground(QRect area);
|
||||
[[nodiscard]] CachedBackground cachedBackground(QSize area);
|
||||
|
||||
rpl::lifetime &lifetime() {
|
||||
return _lifetime;
|
||||
|
@ -462,7 +462,7 @@ private:
|
|||
rpl::event_stream<> _filtersMenuChanged;
|
||||
|
||||
CachedBackground _cachedBackground;
|
||||
QRect _willCacheForArea;
|
||||
QSize _willCacheForArea;
|
||||
crl::time _lastAreaChangeTime = 0;
|
||||
base::Timer _cacheBackgroundTimer;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue