2
0
mirror of https://github.com/kotatogram/kotatogram-desktop synced 2025-09-05 00:55:12 +00:00

Move all background helper methods to chat_theme module.

This commit is contained in:
John Preston
2021-08-27 14:32:18 +03:00
parent 0a1e84ddb2
commit f5a323e40a
16 changed files with 491 additions and 299 deletions

View File

@@ -24,8 +24,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/unixtime.h"
#include "base/crc32hash.h"
#include "data/data_session.h"
#include "data/data_document_resolver.h"
#include "main/main_account.h" // Account::local.
#include "main/main_domain.h" // Domain::activeSessionValue.
#include "ui/chat/chat_theme.h"
#include "ui/image/image.h"
#include "ui/ui_utility.h"
#include "boxes/confirm_box.h"
@@ -43,7 +45,6 @@ namespace {
constexpr auto kThemeFileSizeLimit = 5 * 1024 * 1024;
constexpr auto kBackgroundSizeLimit = 25 * 1024 * 1024;
constexpr auto kNightThemeFile = ":/gui/night.tdesktop-theme"_cs;
constexpr auto kMinimumTiledSize = 512;
struct Applying {
Saved data;
@@ -58,20 +59,6 @@ inline bool AreTestingTheme() {
return !GlobalApplying.paletteForRevert.isEmpty();
}
std::optional<QColor> CalculateImageMonoColor(const QImage &image) {
if (image.isNull()) {
return std::nullopt;
}
const auto bits = reinterpret_cast<const uint32*>(image.constBits());
const auto first = bits[0];
for (auto i = 0; i < image.width() * image.height(); i++) {
if (first != bits[i]) {
return std::nullopt;
}
}
return image.pixelColor(QPoint());
}
[[nodiscard]] bool GoodImageFormatAndSize(const QImage &image) {
return !image.size().isEmpty()
&& (image.format() == QImage::Format_ARGB32_Premultiplied
@@ -646,7 +633,7 @@ QImage ChatBackground::postprocessBackgroundImage(QImage image) {
}
void ChatBackground::set(const Data::WallPaper &paper, QImage image) {
image = PreprocessBackgroundImage(std::move(image));
image = Ui::PreprocessBackgroundImage(std::move(image));
const auto needResetAdjustable = Data::IsDefaultWallPaper(paper)
&& !Data::IsDefaultWallPaper(_paper)
@@ -701,7 +688,7 @@ void ChatBackground::set(const Data::WallPaper &paper, QImage image) {
if (_paper.isPattern() && !image.isNull()) {
if (bgColors.size() < 2) {
auto prepared = postprocessBackgroundImage(
Data::PreparePatternImage(
Ui::PreparePatternImage(
image,
bgColors,
_paper.gradientRotation(),
@@ -752,7 +739,7 @@ void ChatBackground::setPrepared(
Expects(gradient.isNull() || GoodImageFormatAndSize(gradient));
if (!prepared.isNull() && !_paper.isPattern() && _paper.isBlurred()) {
prepared = Data::PrepareBlurredBackground(std::move(prepared));
prepared = Ui::PrepareBlurredBackground(std::move(prepared));
}
if (adjustPaletteRequired()) {
if (!gradient.isNull()) {
@@ -768,40 +755,9 @@ void ChatBackground::setPrepared(
_prepared = std::move(prepared);
_gradient = std::move(gradient);
_imageMonoColor = _gradient.isNull()
? CalculateImageMonoColor(_prepared)
? Ui::CalculateImageMonoColor(_prepared)
: std::nullopt;
prepareImageForTiled();
}
void ChatBackground::prepareImageForTiled() {
const auto width = _prepared.width();
const auto height = _prepared.height();
const auto isSmallForTiled = (width > 0 && height > 0)
&& (width < kMinimumTiledSize || height < kMinimumTiledSize);
if (!isSmallForTiled) {
_preparedForTiled = _prepared;
return;
}
const auto repeatTimesX = qCeil(kMinimumTiledSize / (1. * width));
const auto repeatTimesY = qCeil(kMinimumTiledSize / (1. * height));
_preparedForTiled = QImage(
width * repeatTimesX,
height * repeatTimesY,
QImage::Format_ARGB32_Premultiplied);
_preparedForTiled.setDevicePixelRatio(_prepared.devicePixelRatio());
auto imageForTiledBytes = _preparedForTiled.bits();
auto bytesInLine = width * sizeof(uint32);
for (auto timesY = 0; timesY != repeatTimesY; ++timesY) {
auto imageBytes = _prepared.constBits();
for (auto y = 0; y != height; ++y) {
for (auto timesX = 0; timesX != repeatTimesX; ++timesX) {
memcpy(imageForTiledBytes, imageBytes, bytesInLine);
imageForTiledBytes += bytesInLine;
}
imageBytes += _prepared.bytesPerLine();
imageForTiledBytes += _preparedForTiled.bytesPerLine() - (repeatTimesX * bytesInLine);
}
}
_preparedForTiled = Ui::PrepareImageForTiled(_prepared);
}
void ChatBackground::setPaper(const Data::WallPaper &paper) {
@@ -850,13 +806,13 @@ void ChatBackground::clearEditingTheme(ClearEditing clear) {
}
void ChatBackground::adjustPaletteUsingBackground(const QImage &image) {
adjustPaletteUsingColor(CountAverageColor(image));
adjustPaletteUsingColor(Ui::CountAverageColor(image));
}
void ChatBackground::adjustPaletteUsingColor(QColor color) {
const auto prepared = color.toHsl();
for (const auto &adjustable : _adjustableColors) {
const auto adjusted = AdjustedColor(adjustable.item->c, prepared);
const auto adjusted = Ui::ThemeAdjustedColor(adjustable.item->c, prepared);
adjustable.item.set(
adjusted.red(),
adjusted.green(),
@@ -885,10 +841,7 @@ void ChatBackground::recacheGradientForFill(QImage gradient) {
QImage ChatBackground::createCurrentImage() const {
if (const auto fill = colorForFill()) {
auto result = QImage(
kMinimumTiledSize,
kMinimumTiledSize,
QImage::Format_ARGB32_Premultiplied);
auto result = QImage(512, 512, QImage::Format_ARGB32_Premultiplied);
result.fill(*fill);
return result;
} else if (_gradient.isNull()) {
@@ -1477,64 +1430,6 @@ QString EditingPalettePath() {
return cWorkingDir() + "tdata/editing-theme.tdesktop-palette";
}
QColor CountAverageColor(const QImage &image) {
Expects(image.format() == QImage::Format_ARGB32_Premultiplied
|| image.format() == QImage::Format_RGB32);
uint64 components[3] = { 0 };
const auto w = image.width();
const auto h = image.height();
const auto size = w * h;
if (const auto pix = image.constBits()) {
for (auto i = 0, l = size * 4; i != l; i += 4) {
components[2] += pix[i + 0];
components[1] += pix[i + 1];
components[0] += pix[i + 2];
}
}
if (size) {
for (auto i = 0; i != 3; ++i) {
components[i] /= size;
}
}
return QColor(components[0], components[1], components[2]);
}
QColor AdjustedColor(QColor original, QColor background) {
return QColor::fromHslF(
background.hslHueF(),
background.hslSaturationF(),
original.lightnessF(),
original.alphaF()
).toRgb();
}
QImage PreprocessBackgroundImage(QImage image) {
constexpr auto kMaxSize = 2960;
if (image.format() != QImage::Format_ARGB32_Premultiplied) {
image = std::move(image).convertToFormat(
QImage::Format_ARGB32_Premultiplied);
}
if (image.width() > 40 * image.height()) {
const auto width = 40 * image.height();
const auto height = image.height();
image = image.copy((image.width() - width) / 2, 0, width, height);
} else if (image.height() > 40 * image.width()) {
const auto width = image.width();
const auto height = 40 * image.width();
image = image.copy(0, (image.height() - height) / 2, width, height);
}
if (image.width() > kMaxSize || image.height() > kMaxSize) {
image = image.scaled(
kMaxSize,
kMaxSize,
Qt::KeepAspectRatio,
Qt::SmoothTransformation);
}
return image;
}
bool ReadPaletteValues(const QByteArray &content, Fn<bool(QLatin1String name, QLatin1String value)> callback) {
if (content.size() > kThemeSchemeSizeLimit) {
LOG(("Theme Error: color scheme file too large (should be less than 1 MB, got %2)").arg(content.size()));