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:
@@ -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()));
|
||||
|
Reference in New Issue
Block a user