Add support for SVG patterns in wallpapers.

This commit is contained in:
John Preston 2021-08-11 19:56:12 +03:00
parent e8fc874456
commit 6cadf54874
7 changed files with 62 additions and 29 deletions

View file

@ -411,7 +411,7 @@ void DocumentData::setattributes(
void DocumentData::validateLottieSticker() {
if (type == FileDocument
&& _mimeString == qstr("application/x-tgsticker")) {
&& hasMimeType(qstr("application/x-tgsticker"))) {
type = StickerDocument;
_additional = std::make_unique<StickerData>();
sticker()->animated = true;
@ -442,9 +442,8 @@ bool DocumentData::checkWallPaperProperties() {
|| !dimensions.height()
|| dimensions.width() > Storage::kMaxWallPaperDimension
|| dimensions.height() > Storage::kMaxWallPaperDimension
|| size > Storage::kMaxWallPaperInMemory
|| mimeString() == qstr("application/x-tgwallpattern")) {
return false; // #TODO themes support svg patterns
|| size > Storage::kMaxWallPaperInMemory) {
return false;
}
type = WallPaperDocument;
return true;
@ -487,9 +486,18 @@ bool DocumentData::isWallPaper() const {
}
bool DocumentData::isPatternWallPaper() const {
return isWallPaper()
&& (isPatternWallPaperPNG() || isPatternWallPaperSVG());
}
bool DocumentData::isPatternWallPaperPNG() const {
return isWallPaper() && hasMimeType(qstr("image/png"));
}
bool DocumentData::isPatternWallPaperSVG() const {
return isWallPaper() && hasMimeType(qstr("application/x-tgwallpattern"));
}
bool DocumentData::hasThumbnail() const {
return _thumbnail.location.valid();
}
@ -661,9 +669,9 @@ bool DocumentData::saveToCache() const {
&& ((type == StickerDocument)
|| isAnimation()
|| isVoiceMessage()
|| (type == WallPaperDocument)
|| isWallPaper()
|| isTheme()
|| (mimeString() == qstr("image/png")
|| (hasMimeType(qstr("image/png"))
&& _filename.startsWith("image_")));
}
@ -1233,11 +1241,12 @@ QString DocumentData::mimeString() const {
}
bool DocumentData::hasMimeType(QLatin1String mime) const {
return !_mimeString.compare(mime, Qt::CaseInsensitive);
return (_mimeString == mime);
}
void DocumentData::setMimeString(const QString &mime) {
_mimeString = mime;
_mimeString = std::move(_mimeString).toLower();
}
MediaKey DocumentData::mediaKey() const {
@ -1263,7 +1272,7 @@ uint8 DocumentData::cacheTag() const {
return Data::kVideoMessageCacheTag;
} else if (isAnimation()) {
return Data::kAnimationCacheTag;
} else if (type == WallPaperDocument) {
} else if (isWallPaper()) {
return Data::kImageCacheTag;
}
return 0;
@ -1298,14 +1307,9 @@ bool DocumentData::isGifv() const {
}
bool DocumentData::isTheme() const {
return
_mimeString == qstr("application/x-tgtheme-tdesktop")
|| _filename.endsWith(
qstr(".tdesktop-theme"),
Qt::CaseInsensitive)
|| _filename.endsWith(
qstr(".tdesktop-palette"),
Qt::CaseInsensitive);
return hasMimeType(qstr("application/x-tgtheme-tdesktop"))
|| _filename.endsWith(qstr(".tdesktop-theme"), Qt::CaseInsensitive)
|| _filename.endsWith(qstr(".tdesktop-palette"), Qt::CaseInsensitive);
}
bool DocumentData::isSong() const {

View file

@ -155,6 +155,8 @@ public:
bool checkWallPaperProperties();
[[nodiscard]] bool isWallPaper() const;
[[nodiscard]] bool isPatternWallPaper() const;
[[nodiscard]] bool isPatternWallPaperPNG() const;
[[nodiscard]] bool isPatternWallPaperSVG() const;
[[nodiscard]] bool hasThumbnail() const;
[[nodiscard]] bool thumbnailLoading() const;

View file

@ -39,6 +39,8 @@ enum class FileType {
Video,
AnimatedSticker,
WallPaper,
WallPatternPNG,
WallPatternSVG,
Theme,
};
@ -60,6 +62,15 @@ enum class FileType {
return Lottie::ReadThumbnail(Lottie::ReadContent(data, path));
} else if (type == FileType::Theme) {
return Window::Theme::GeneratePreview(data, path);
} else if (type == FileType::WallPatternSVG) {
return Images::Read({
.path = path,
.content = std::move(data),
.maxSize = QSize(
kWallPaperThumbnailLimit,
kWallPaperThumbnailLimit),
.gzipSvg = true,
}).image;
}
auto buffer = QBuffer(&data);
auto file = QFile(path);
@ -390,7 +401,11 @@ void DocumentMedia::checkStickerLarge(not_null<FileLoader*> loader) {
void DocumentMedia::GenerateGoodThumbnail(
not_null<DocumentData*> document,
QByteArray data) {
const auto type = document->isWallPaper()
const auto type = document->isPatternWallPaperSVG()
? FileType::WallPatternSVG
: document->isPatternWallPaperPNG()
? FileType::WallPatternPNG
: document->isWallPaper()
? FileType::WallPaper
: document->isTheme()
? FileType::Theme
@ -415,7 +430,8 @@ void DocumentMedia::GenerateGoodThumbnail(
auto buffer = QBuffer(&bytes);
const auto format = (type == FileType::AnimatedSticker)
? "WEBP"
: (type == FileType::WallPaper && result.hasAlphaChannel())
: (type == FileType::WallPatternPNG
|| type == FileType::WallPatternSVG)
? "PNG"
: "JPG";
result.save(&buffer, format, kGoodThumbQuality);

View file

@ -33,6 +33,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Data {
namespace {
constexpr auto kMaxWallpaperSize = 3072;
void LaunchWithWarning(
// not_null<Window::Controller*> controller,
const QString &name,
@ -173,27 +175,38 @@ bool IsIpRevealingName(const QString &filepath) {
);
}
[[nodiscard]] QImage ReadImage(
const QString &path,
const QByteArray &content,
bool gzipSvg) {
return Images::Read({
.path = path,
.content = content,
.maxSize = QSize(kMaxWallpaperSize, kMaxWallpaperSize),
.gzipSvg = gzipSvg,
}).image;
}
base::binary_guard ReadImageAsync(
not_null<Data::DocumentMedia*> media,
FnMut<QImage(QImage)> postprocess,
FnMut<void(QImage&&)> done) {
auto result = base::binary_guard();
const auto gzipSvg = media->owner()->isPatternWallPaperSVG();
crl::async([
gzipSvg,
bytes = media->bytes(),
path = media->owner()->filepath(),
postprocess = std::move(postprocess),
guard = result.make_guard(),
callback = std::move(done)
]() mutable {
auto read = Images::Read({
.path = path,
.content = bytes,
});
auto image = ReadImage(path, bytes, gzipSvg);
if (postprocess) {
read.image = postprocess(std::move(read.image));
image = postprocess(std::move(image));
}
crl::on_main(std::move(guard), [
image = std::move(read.image),
image = std::move(image),
callback = std::move(callback)
]() mutable {
callback(std::move(image));

View file

@ -35,9 +35,7 @@ DocumentGenericPreview DocumentGenericPreview::Create(
: document->filename())
: tr::lng_message_empty(tr::now)).toLower();
auto lastDot = name.lastIndexOf('.');
const auto mime = document
? document->mimeString().toLower()
: QString();
const auto mime = document ? document->mimeString() : QString();
if (name.endsWith(qstr(".doc")) ||
name.endsWith(qstr(".docx")) ||
name.endsWith(qstr(".txt")) ||

@ -1 +1 @@
Subproject commit 2f9bda2cc7b8c94abe34f501b270df8533a7b141
Subproject commit 06960b493d58d7c4e642dc38384d5f0db5340f1c

@ -1 +1 @@
Subproject commit 2bd63281b58d54aa129da78f05f0e6e73e5d63c9
Subproject commit dd88f8fa41a06bdf3128276d8084cfa4f087dee7