Estimate size of images to avoid layout shifts (#5192)
This commit is contained in:
+11
-9
@@ -318,7 +318,7 @@ Image::~Image()
|
||||
}
|
||||
}
|
||||
|
||||
ImagePtr Image::fromUrl(const Url &url, qreal scale)
|
||||
ImagePtr Image::fromUrl(const Url &url, qreal scale, QSize expectedSize)
|
||||
{
|
||||
static std::unordered_map<Url, std::weak_ptr<Image>> cache;
|
||||
static std::mutex mutex;
|
||||
@@ -329,7 +329,7 @@ ImagePtr Image::fromUrl(const Url &url, qreal scale)
|
||||
|
||||
if (!shared)
|
||||
{
|
||||
cache[url] = shared = ImagePtr(new Image(url, scale));
|
||||
cache[url] = shared = ImagePtr(new Image(url, scale, expectedSize));
|
||||
}
|
||||
|
||||
return shared;
|
||||
@@ -382,9 +382,11 @@ Image::Image()
|
||||
{
|
||||
}
|
||||
|
||||
Image::Image(const Url &url, qreal scale)
|
||||
Image::Image(const Url &url, qreal scale, QSize expectedSize)
|
||||
: url_(url)
|
||||
, scale_(scale)
|
||||
, expectedSize_(expectedSize.isValid() ? expectedSize
|
||||
: (QSize(16, 16) * scale))
|
||||
, shouldLoad_(true)
|
||||
, frames_(std::make_unique<detail::Frames>())
|
||||
{
|
||||
@@ -477,11 +479,11 @@ int Image::width() const
|
||||
|
||||
if (auto pixmap = this->frames_->first())
|
||||
{
|
||||
return int(pixmap->width() * this->scale_);
|
||||
return static_cast<int>(pixmap->width() * this->scale_);
|
||||
}
|
||||
|
||||
// No frames loaded, use our default magic width 16
|
||||
return 16;
|
||||
// No frames loaded, use the expected size
|
||||
return static_cast<int>(this->expectedSize_.width() * this->scale_);
|
||||
}
|
||||
|
||||
int Image::height() const
|
||||
@@ -490,11 +492,11 @@ int Image::height() const
|
||||
|
||||
if (auto pixmap = this->frames_->first())
|
||||
{
|
||||
return int(pixmap->height() * this->scale_);
|
||||
return static_cast<int>(pixmap->height() * this->scale_);
|
||||
}
|
||||
|
||||
// No frames loaded, use our default magic height 16
|
||||
return 16;
|
||||
// No frames loaded, use the expected size
|
||||
return static_cast<int>(this->expectedSize_.height() * this->scale_);
|
||||
}
|
||||
|
||||
void Image::actuallyLoad()
|
||||
|
||||
+11
-4
@@ -73,7 +73,8 @@ public:
|
||||
Image(Image &&) = delete;
|
||||
Image &operator=(Image &&) = delete;
|
||||
|
||||
static ImagePtr fromUrl(const Url &url, qreal scale = 1);
|
||||
static ImagePtr fromUrl(const Url &url, qreal scale = 1,
|
||||
QSize expectedSize = {});
|
||||
static ImagePtr fromResourcePixmap(const QPixmap &pixmap, qreal scale = 1);
|
||||
static ImagePtr getEmpty();
|
||||
|
||||
@@ -93,7 +94,7 @@ public:
|
||||
|
||||
private:
|
||||
Image();
|
||||
Image(const Url &url, qreal scale);
|
||||
Image(const Url &url, qreal scale, QSize expectedSize);
|
||||
Image(qreal scale);
|
||||
|
||||
void setPixmap(const QPixmap &pixmap);
|
||||
@@ -102,12 +103,18 @@ private:
|
||||
|
||||
const Url url_{};
|
||||
const qreal scale_{1};
|
||||
/// @brief The expected size of this image once its loaded.
|
||||
///
|
||||
/// This doesn't represent the actual size (it can be different) - it's
|
||||
/// just an estimation and provided to avoid (large) layout shifts when
|
||||
/// loading images.
|
||||
const QSize expectedSize_{16, 16};
|
||||
std::atomic_bool empty_{false};
|
||||
|
||||
mutable std::chrono::time_point<std::chrono::steady_clock> lastUsed_;
|
||||
|
||||
bool shouldLoad_{false};
|
||||
|
||||
mutable std::chrono::time_point<std::chrono::steady_clock> lastUsed_;
|
||||
|
||||
// gui thread only
|
||||
std::unique_ptr<detail::Frames> frames_{};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user