forked from github_mirror/framelesshelper
mica material: support reading very large image files
This commit is contained in:
parent
fa5389a0fc
commit
7c0d8c4b11
2
cmake
2
cmake
|
@ -1 +1 @@
|
||||||
Subproject commit 69aa8ca8ed5ad4b06d0bc024293641b1a14884ff
|
Subproject commit c1e8081d4de985e5c7edbe2d5209860cb1ceb62f
|
|
@ -64,7 +64,7 @@ int main(int argc, char *argv[])
|
||||||
FramelessHelper::Core::setApplicationOSThemeAware();
|
FramelessHelper::Core::setApplicationOSThemeAware();
|
||||||
|
|
||||||
FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow);
|
FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow);
|
||||||
FramelessConfig::instance()->set(Global::Option::DisableLazyInitializationForMicaMaterial);
|
//FramelessConfig::instance()->set(Global::Option::DisableLazyInitializationForMicaMaterial);
|
||||||
|
|
||||||
// Enable QtRHI debug output if not explicitly requested by the user.
|
// Enable QtRHI debug output if not explicitly requested by the user.
|
||||||
if (!qEnvironmentVariableIsSet("QSG_INFO")) {
|
if (!qEnvironmentVariableIsSet("QSG_INFO")) {
|
||||||
|
@ -129,7 +129,7 @@ int main(int argc, char *argv[])
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 4, 0))
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 4, 0))
|
||||||
QObject::connect(engine.get(), &QQmlApplicationEngine::objectCreationFailed, qApp,
|
QObject::connect(engine.get(), &QQmlApplicationEngine::objectCreationFailed, application.get(),
|
||||||
[](const QUrl &url){
|
[](const QUrl &url){
|
||||||
qCritical() << "The QML engine failed to create component:" << url;
|
qCritical() << "The QML engine failed to create component:" << url;
|
||||||
QCoreApplication::exit(-1);
|
QCoreApplication::exit(-1);
|
||||||
|
|
|
@ -29,6 +29,12 @@
|
||||||
|
|
||||||
FRAMELESSHELPER_USE_NAMESPACE
|
FRAMELESSHELPER_USE_NAMESPACE
|
||||||
|
|
||||||
|
#define CREATE_WINDOW(Name) \
|
||||||
|
const auto Name = std::make_unique<Widget>(); \
|
||||||
|
Name->setObjectName(FRAMELESSHELPER_STRING_LITERAL(#Name)); \
|
||||||
|
Name->waitReady(); \
|
||||||
|
Name->show();
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
Log::setup(FRAMELESSHELPER_STRING_LITERAL("widget"));
|
Log::setup(FRAMELESSHELPER_STRING_LITERAL("widget"));
|
||||||
|
@ -51,17 +57,12 @@ int main(int argc, char *argv[])
|
||||||
FramelessHelper::Core::setApplicationOSThemeAware();
|
FramelessHelper::Core::setApplicationOSThemeAware();
|
||||||
|
|
||||||
FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow);
|
FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow);
|
||||||
FramelessConfig::instance()->set(Global::Option::DisableLazyInitializationForMicaMaterial);
|
//FramelessConfig::instance()->set(Global::Option::DisableLazyInitializationForMicaMaterial);
|
||||||
|
|
||||||
const auto window1 = std::make_unique<Widget>();
|
CREATE_WINDOW(window1)
|
||||||
window1->setObjectName(FRAMELESSHELPER_STRING_LITERAL("window1"));
|
CREATE_WINDOW(window2)
|
||||||
window1->waitReady();
|
CREATE_WINDOW(window3)
|
||||||
window1->show();
|
CREATE_WINDOW(window4)
|
||||||
|
|
||||||
const auto window2 = std::make_unique<Widget>();
|
|
||||||
window2->setObjectName(FRAMELESSHELPER_STRING_LITERAL("window2"));
|
|
||||||
window2->waitReady();
|
|
||||||
window2->show();
|
|
||||||
|
|
||||||
return QCoreApplication::exec();
|
return QCoreApplication::exec();
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,10 @@ private:
|
||||||
bool fallbackEnabled = true;
|
bool fallbackEnabled = true;
|
||||||
QBrush micaBrush = {};
|
QBrush micaBrush = {};
|
||||||
bool initialized = false;
|
bool initialized = false;
|
||||||
|
struct {
|
||||||
|
qreal x = 0;
|
||||||
|
qreal y = 0;
|
||||||
|
} transform = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
FRAMELESSHELPER_END_NAMESPACE
|
FRAMELESSHELPER_END_NAMESPACE
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include <QtCore/qloggingcategory.h>
|
#include <QtCore/qloggingcategory.h>
|
||||||
#include <QtGui/qpixmap.h>
|
#include <QtGui/qpixmap.h>
|
||||||
#include <QtGui/qimage.h>
|
#include <QtGui/qimage.h>
|
||||||
|
#include <QtGui/qimagereader.h>
|
||||||
#include <QtGui/qpainter.h>
|
#include <QtGui/qpainter.h>
|
||||||
#include <QtGui/qscreen.h>
|
#include <QtGui/qscreen.h>
|
||||||
#include <QtGui/qguiapplication.h>
|
#include <QtGui/qguiapplication.h>
|
||||||
|
@ -56,6 +57,9 @@ static Q_LOGGING_CATEGORY(lcMicaMaterial, "wangwenx190.framelesshelper.core.mica
|
||||||
|
|
||||||
using namespace Global;
|
using namespace Global;
|
||||||
|
|
||||||
|
[[maybe_unused]] static constexpr const QSize kMaximumPictureSize = { 1920, 1080 };
|
||||||
|
[[maybe_unused]] static constexpr const QImage::Format kDefaultImageFormat = QImage::Format_ARGB32_Premultiplied;
|
||||||
|
|
||||||
[[maybe_unused]] static constexpr const qreal kDefaultTintOpacity = 0.7;
|
[[maybe_unused]] static constexpr const qreal kDefaultTintOpacity = 0.7;
|
||||||
[[maybe_unused]] static constexpr const qreal kDefaultNoiseOpacity = 0.04;
|
[[maybe_unused]] static constexpr const qreal kDefaultNoiseOpacity = 0.04;
|
||||||
[[maybe_unused]] static constexpr const qreal kDefaultBlurRadius = 128.0;
|
[[maybe_unused]] static constexpr const qreal kDefaultBlurRadius = 128.0;
|
||||||
|
@ -77,6 +81,26 @@ struct MicaMaterialData
|
||||||
|
|
||||||
Q_GLOBAL_STATIC(MicaMaterialData, g_micaMaterialData)
|
Q_GLOBAL_STATIC(MicaMaterialData, g_micaMaterialData)
|
||||||
|
|
||||||
|
[[maybe_unused]] [[nodiscard]] static inline constexpr bool operator>(const QSize &lhs, const QSize &rhs) noexcept
|
||||||
|
{
|
||||||
|
return ((lhs.width() * lhs.height()) > (rhs.width() * rhs.height()));
|
||||||
|
}
|
||||||
|
|
||||||
|
[[maybe_unused]] [[nodiscard]] static inline constexpr bool operator>=(const QSize &lhs, const QSize &rhs) noexcept
|
||||||
|
{
|
||||||
|
return (operator>(lhs, rhs) || operator==(lhs, rhs));
|
||||||
|
}
|
||||||
|
|
||||||
|
[[maybe_unused]] [[nodiscard]] static inline constexpr bool operator<(const QSize &lhs, const QSize &rhs) noexcept
|
||||||
|
{
|
||||||
|
return (operator!=(lhs, rhs) && !operator>(lhs, rhs));
|
||||||
|
}
|
||||||
|
|
||||||
|
[[maybe_unused]] [[nodiscard]] static inline constexpr bool operator<=(const QSize &lhs, const QSize &rhs) noexcept
|
||||||
|
{
|
||||||
|
return (operator<(lhs, rhs) || operator==(lhs, rhs));
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef FRAMELESSHELPER_CORE_NO_PRIVATE
|
#ifndef FRAMELESSHELPER_CORE_NO_PRIVATE
|
||||||
template<const int shift>
|
template<const int shift>
|
||||||
[[nodiscard]] static inline constexpr int qt_static_shift(const int value)
|
[[nodiscard]] static inline constexpr int qt_static_shift(const int value)
|
||||||
|
@ -192,11 +216,11 @@ static inline void qt_blurrow(QImage &im, const int line, const int alpha)
|
||||||
template<const int aprec, const int zprec, const bool alphaOnly>
|
template<const int aprec, const int zprec, const bool alphaOnly>
|
||||||
static inline void expblur(QImage &img, qreal radius, const bool improvedQuality = false, const int transposed = 0)
|
static inline void expblur(QImage &img, qreal radius, const bool improvedQuality = false, const int transposed = 0)
|
||||||
{
|
{
|
||||||
Q_ASSERT((img.format() == QImage::Format_ARGB32_Premultiplied)
|
Q_ASSERT((img.format() == kDefaultImageFormat)
|
||||||
|| (img.format() == QImage::Format_RGB32)
|
|| (img.format() == QImage::Format_RGB32)
|
||||||
|| (img.format() == QImage::Format_Indexed8)
|
|| (img.format() == QImage::Format_Indexed8)
|
||||||
|| (img.format() == QImage::Format_Grayscale8));
|
|| (img.format() == QImage::Format_Grayscale8));
|
||||||
if ((img.format() != QImage::Format_ARGB32_Premultiplied)
|
if ((img.format() != kDefaultImageFormat)
|
||||||
&& (img.format() != QImage::Format_RGB32)
|
&& (img.format() != QImage::Format_RGB32)
|
||||||
&& (img.format() != QImage::Format_Indexed8)
|
&& (img.format() != QImage::Format_Indexed8)
|
||||||
&& (img.format() != QImage::Format_Grayscale8)) {
|
&& (img.format() != QImage::Format_Grayscale8)) {
|
||||||
|
@ -345,9 +369,9 @@ static inline void expblur(QImage &img, qreal radius, const bool improvedQuality
|
||||||
|
|
||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
if ((source.format() != QImage::Format_ARGB32_Premultiplied)
|
if ((source.format() != kDefaultImageFormat)
|
||||||
&& (source.format() != QImage::Format_RGB32)) {
|
&& (source.format() != QImage::Format_RGB32)) {
|
||||||
srcImage = source.convertToFormat(QImage::Format_ARGB32_Premultiplied);
|
srcImage = source.convertToFormat(kDefaultImageFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
QImage dest(source.width() / 2, source.height() / 2, srcImage.format());
|
QImage dest(source.width() / 2, source.height() / 2, srcImage.format());
|
||||||
|
@ -377,9 +401,9 @@ static inline void expblur(QImage &img, qreal radius, const bool improvedQuality
|
||||||
[[maybe_unused]] static inline void qt_blurImage(QPainter *p, QImage &blurImage,
|
[[maybe_unused]] static inline void qt_blurImage(QPainter *p, QImage &blurImage,
|
||||||
qreal radius, const bool quality, const bool alphaOnly, const int transposed = 0)
|
qreal radius, const bool quality, const bool alphaOnly, const int transposed = 0)
|
||||||
{
|
{
|
||||||
if ((blurImage.format() != QImage::Format_ARGB32_Premultiplied)
|
if ((blurImage.format() != kDefaultImageFormat)
|
||||||
&& (blurImage.format() != QImage::Format_RGB32)) {
|
&& (blurImage.format() != QImage::Format_RGB32)) {
|
||||||
blurImage = blurImage.convertToFormat(QImage::Format_ARGB32_Premultiplied);
|
blurImage = blurImage.convertToFormat(kDefaultImageFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
qreal scale = 1.0;
|
qreal scale = 1.0;
|
||||||
|
@ -508,21 +532,49 @@ void MicaMaterialPrivate::maybeGenerateBlurredWallpaper(const bool force)
|
||||||
if (!g_micaMaterialData()->blurredWallpaper.isNull() && !force) {
|
if (!g_micaMaterialData()->blurredWallpaper.isNull() && !force) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const QSize size = QGuiApplication::primaryScreen()->virtualSize();
|
QSize monitorSize = QGuiApplication::primaryScreen()->virtualSize();
|
||||||
g_micaMaterialData()->blurredWallpaper = QPixmap(size);
|
if (monitorSize.isEmpty()) {
|
||||||
g_micaMaterialData()->blurredWallpaper.fill(kDefaultTransparentColor);
|
WARNING << "Failed to retrieve the monitor size. Using default size (1920x1080) instead ...";
|
||||||
|
monitorSize = kMaximumPictureSize;
|
||||||
|
}
|
||||||
|
const QSize imageSize = (monitorSize > kMaximumPictureSize ? kMaximumPictureSize : monitorSize);
|
||||||
const QString wallpaperFilePath = Utils::getWallpaperFilePath();
|
const QString wallpaperFilePath = Utils::getWallpaperFilePath();
|
||||||
if (wallpaperFilePath.isEmpty()) {
|
if (wallpaperFilePath.isEmpty()) {
|
||||||
WARNING << "Failed to retrieve the wallpaper file path.";
|
WARNING << "Failed to retrieve the wallpaper file path.";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QImage image(wallpaperFilePath);
|
QImageReader reader(wallpaperFilePath);
|
||||||
|
if (!reader.canRead()) {
|
||||||
|
WARNING << "Qt can't read the wallpaper file:" << reader.errorString();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const QSize actualSize = reader.size();
|
||||||
|
if (actualSize.isEmpty()) {
|
||||||
|
WARNING << "The wallpaper picture size is invalid.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const QSize correctedSize = (actualSize > kMaximumPictureSize ? kMaximumPictureSize : actualSize);
|
||||||
|
if (actualSize == correctedSize) {
|
||||||
|
transform = {};
|
||||||
|
} else {
|
||||||
|
DEBUG << "The wallpaper picture size is greater than 1920x1080, it will be shrinked to reduce memory consumption.";
|
||||||
|
reader.setScaledSize(correctedSize);
|
||||||
|
transform.x = qreal(correctedSize.width()) / qreal(actualSize.width());
|
||||||
|
transform.y = qreal(correctedSize.height()) / qreal(actualSize.height());
|
||||||
|
}
|
||||||
|
QImage image(correctedSize, kDefaultImageFormat);
|
||||||
|
if (!reader.read(&image)) {
|
||||||
|
WARNING << "Failed to read the wallpaper image:" << reader.errorString();
|
||||||
|
transform = {};
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (image.isNull()) {
|
if (image.isNull()) {
|
||||||
WARNING << "QImage doesn't support this kind of file:" << wallpaperFilePath;
|
WARNING << "The obtained image data is null.";
|
||||||
|
transform = {};
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
WallpaperAspectStyle aspectStyle = Utils::getWallpaperAspectStyle();
|
WallpaperAspectStyle aspectStyle = Utils::getWallpaperAspectStyle();
|
||||||
QImage buffer(size, QImage::Format_ARGB32_Premultiplied);
|
QImage buffer(imageSize, kDefaultImageFormat);
|
||||||
#ifdef Q_OS_WINDOWS
|
#ifdef Q_OS_WINDOWS
|
||||||
if (aspectStyle == WallpaperAspectStyle::Center) {
|
if (aspectStyle == WallpaperAspectStyle::Center) {
|
||||||
buffer.fill(kDefaultBlackColor);
|
buffer.fill(kDefaultBlackColor);
|
||||||
|
@ -538,11 +590,11 @@ void MicaMaterialPrivate::maybeGenerateBlurredWallpaper(const bool force)
|
||||||
mode = Qt::KeepAspectRatio;
|
mode = Qt::KeepAspectRatio;
|
||||||
}
|
}
|
||||||
QSize newSize = image.size();
|
QSize newSize = image.size();
|
||||||
newSize.scale(size, mode);
|
newSize.scale(imageSize, mode);
|
||||||
image = image.scaled(newSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
image = image.scaled(newSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
||||||
}
|
}
|
||||||
static constexpr const QPoint desktopOriginPoint = {0, 0};
|
static constexpr const QPoint desktopOriginPoint = {0, 0};
|
||||||
const QRect desktopRect = {desktopOriginPoint, size};
|
const QRect desktopRect = {desktopOriginPoint, imageSize};
|
||||||
if (aspectStyle == WallpaperAspectStyle::Tile) {
|
if (aspectStyle == WallpaperAspectStyle::Tile) {
|
||||||
QPainter bufferPainter(&buffer);
|
QPainter bufferPainter(&buffer);
|
||||||
bufferPainter.setRenderHints(QPainter::Antialiasing |
|
bufferPainter.setRenderHints(QPainter::Antialiasing |
|
||||||
|
@ -555,6 +607,8 @@ void MicaMaterialPrivate::maybeGenerateBlurredWallpaper(const bool force)
|
||||||
const QRect rect = alignedRect(Qt::LeftToRight, Qt::AlignCenter, image.size(), desktopRect);
|
const QRect rect = alignedRect(Qt::LeftToRight, Qt::AlignCenter, image.size(), desktopRect);
|
||||||
bufferPainter.drawImage(rect.topLeft(), image);
|
bufferPainter.drawImage(rect.topLeft(), image);
|
||||||
}
|
}
|
||||||
|
g_micaMaterialData()->blurredWallpaper = QPixmap(imageSize);
|
||||||
|
g_micaMaterialData()->blurredWallpaper.fill(kDefaultTransparentColor);
|
||||||
QPainter painter(&g_micaMaterialData()->blurredWallpaper);
|
QPainter painter(&g_micaMaterialData()->blurredWallpaper);
|
||||||
painter.setRenderHints(QPainter::Antialiasing |
|
painter.setRenderHints(QPainter::Antialiasing |
|
||||||
QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform);
|
QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform);
|
||||||
|
@ -575,7 +629,7 @@ void MicaMaterialPrivate::updateMaterialBrush()
|
||||||
framelesshelpercore_initResource();
|
framelesshelpercore_initResource();
|
||||||
static const QImage noiseTexture = QImage(kNoiseImageFilePath);
|
static const QImage noiseTexture = QImage(kNoiseImageFilePath);
|
||||||
#endif // FRAMELESSHELPER_CORE_NO_BUNDLE_RESOURCE
|
#endif // FRAMELESSHELPER_CORE_NO_BUNDLE_RESOURCE
|
||||||
QImage micaTexture = QImage(QSize(64, 64), QImage::Format_ARGB32_Premultiplied);
|
QImage micaTexture = QImage(QSize(64, 64), kDefaultImageFormat);
|
||||||
QColor fillColor = ((FramelessManager::instance()->systemTheme() == SystemTheme::Dark) ? kDefaultSystemDarkColor : kDefaultSystemLightColor2);
|
QColor fillColor = ((FramelessManager::instance()->systemTheme() == SystemTheme::Dark) ? kDefaultSystemDarkColor : kDefaultSystemLightColor2);
|
||||||
fillColor.setAlphaF(0.9f);
|
fillColor.setAlphaF(0.9f);
|
||||||
micaTexture.fill(fillColor);
|
micaTexture.fill(fillColor);
|
||||||
|
@ -599,20 +653,31 @@ void MicaMaterialPrivate::updateMaterialBrush()
|
||||||
void MicaMaterialPrivate::paint(QPainter *painter, const QSize &size, const QPoint &pos, const bool active)
|
void MicaMaterialPrivate::paint(QPainter *painter, const QSize &size, const QPoint &pos, const bool active)
|
||||||
{
|
{
|
||||||
Q_ASSERT(painter);
|
Q_ASSERT(painter);
|
||||||
if (!painter) {
|
Q_ASSERT(!size.isEmpty());
|
||||||
|
if (!painter || size.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
prepareGraphicsResources();
|
prepareGraphicsResources();
|
||||||
static constexpr const QPoint originPoint = {0, 0};
|
static constexpr const QPointF originPoint = {0, 0};
|
||||||
|
QPointF correctedPos = pos;
|
||||||
|
QSizeF correctedSize = size;
|
||||||
|
if (!qFuzzyIsNull(transform.x) && (transform.x > qreal(0)) && !qFuzzyCompare(transform.x, qreal(1))) {
|
||||||
|
correctedPos.setX(correctedPos.x() * transform.x);
|
||||||
|
correctedSize.setWidth(correctedSize.width() * transform.x);
|
||||||
|
}
|
||||||
|
if (!qFuzzyIsNull(transform.y) && (transform.y > qreal(0)) && !qFuzzyCompare(transform.y, qreal(1))) {
|
||||||
|
correctedPos.setY(correctedPos.y() * transform.y);
|
||||||
|
correctedSize.setHeight(correctedSize.height() * transform.y);
|
||||||
|
}
|
||||||
painter->save();
|
painter->save();
|
||||||
painter->setRenderHints(QPainter::Antialiasing |
|
painter->setRenderHints(QPainter::Antialiasing |
|
||||||
QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform);
|
QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform);
|
||||||
if (active) {
|
if (active) {
|
||||||
painter->drawPixmap(originPoint, g_micaMaterialData()->blurredWallpaper, QRect(pos, size));
|
painter->drawPixmap(originPoint, g_micaMaterialData()->blurredWallpaper, QRectF{correctedPos, correctedSize});
|
||||||
}
|
}
|
||||||
painter->setCompositionMode(QPainter::CompositionMode_SourceOver);
|
painter->setCompositionMode(QPainter::CompositionMode_SourceOver);
|
||||||
painter->setOpacity(qreal(1));
|
painter->setOpacity(qreal(1));
|
||||||
painter->fillRect(QRect{originPoint, size}, [this, active]() -> QBrush {
|
painter->fillRect(QRectF{originPoint, correctedSize}, [this, active]() -> QBrush {
|
||||||
if (!fallbackEnabled || active) {
|
if (!fallbackEnabled || active) {
|
||||||
return micaBrush;
|
return micaBrush;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue