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