QIcon::addFile() delay-load icons when a proper size is given
Delay-load the icon within QPixmapEngine::addFile() when a proper size is given - this speeds up QIcon creation and also allows to let QIcon::actualSize() return the correct size of an QIcon instead the given one. This is especially useful e.g. when a 32x32 icon has a smaller width or height and it should be centered during painting. Also add an optimization for multi-image formats to check for the correct size without decoding the image. Pick-to: 6.8 Task-number: QTBUG-59621 Change-Id: I7ed930ae3f65a8b3a272f70bcc2958980f9f02f2 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
This commit is contained in:
parent
6b23a3c5e4
commit
94a3a492f5
@ -43,6 +43,7 @@ public:
|
|||||||
bool supportsReadSize() const { return m_reader.supportsOption(QImageIOHandler::Size); }
|
bool supportsReadSize() const { return m_reader.supportsOption(QImageIOHandler::Size); }
|
||||||
QSize size() const { return m_reader.size(); }
|
QSize size() const { return m_reader.size(); }
|
||||||
bool jumpToNextImage() { return m_reader.jumpToNextImage(); }
|
bool jumpToNextImage() { return m_reader.jumpToNextImage(); }
|
||||||
|
void jumpToImage(int index) { m_reader.jumpToImage(index); }
|
||||||
|
|
||||||
bool read(QImage *image)
|
bool read(QImage *image)
|
||||||
{
|
{
|
||||||
@ -244,7 +245,7 @@ QPixmapIconEngineEntry *QPixmapIconEngine::tryMatch(const QSize &size, qreal sca
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QPixmapIconEngineEntry *QPixmapIconEngine::bestMatch(const QSize &size, qreal scale, QIcon::Mode mode, QIcon::State state, bool sizeOnly)
|
QPixmapIconEngineEntry *QPixmapIconEngine::bestMatch(const QSize &size, qreal scale, QIcon::Mode mode, QIcon::State state)
|
||||||
{
|
{
|
||||||
QPixmapIconEngineEntry *pe = tryMatch(size, scale, mode, state);
|
QPixmapIconEngineEntry *pe = tryMatch(size, scale, mode, state);
|
||||||
while (!pe){
|
while (!pe){
|
||||||
@ -287,10 +288,38 @@ QPixmapIconEngineEntry *QPixmapIconEngine::bestMatch(const QSize &size, qreal sc
|
|||||||
return pe;
|
return pe;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sizeOnly ? (pe->size.isNull() || !pe->size.isValid()) : pe->pixmap.isNull()) {
|
if (pe->pixmap.isNull()) {
|
||||||
pe->pixmap = QPixmap(pe->fileName);
|
// delay-load the image
|
||||||
if (!pe->pixmap.isNull())
|
ImageReader imageReader(pe->fileName);
|
||||||
pe->size = pe->pixmap.size();
|
QImage image, prevImage;
|
||||||
|
const QSize realSize = size * scale;
|
||||||
|
bool fittingImageFound = false;
|
||||||
|
if (imageReader.supportsReadSize()) {
|
||||||
|
// find the image with the best size without loading the entire image
|
||||||
|
do {
|
||||||
|
fittingImageFound = imageReader.size() == realSize;
|
||||||
|
} while (!fittingImageFound && imageReader.jumpToNextImage());
|
||||||
|
}
|
||||||
|
if (!fittingImageFound) {
|
||||||
|
imageReader.jumpToImage(0);
|
||||||
|
while (imageReader.read(&image) && image.size() != realSize)
|
||||||
|
prevImage = image;
|
||||||
|
if (image.isNull())
|
||||||
|
image = prevImage;
|
||||||
|
} else {
|
||||||
|
imageReader.read(&image);
|
||||||
|
}
|
||||||
|
if (!image.isNull()) {
|
||||||
|
pe->pixmap.convertFromImage(image);
|
||||||
|
if (!pe->pixmap.isNull()) {
|
||||||
|
pe->size = pe->pixmap.size();
|
||||||
|
pe->pixmap.setDevicePixelRatio(scale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!pe->size.isValid()) {
|
||||||
|
removePixmapEntry(pe);
|
||||||
|
pe = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return pe;
|
return pe;
|
||||||
@ -304,7 +333,7 @@ QPixmap QPixmapIconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::St
|
|||||||
QPixmap QPixmapIconEngine::scaledPixmap(const QSize &size, QIcon::Mode mode, QIcon::State state, qreal scale)
|
QPixmap QPixmapIconEngine::scaledPixmap(const QSize &size, QIcon::Mode mode, QIcon::State state, qreal scale)
|
||||||
{
|
{
|
||||||
QPixmap pm;
|
QPixmap pm;
|
||||||
QPixmapIconEngineEntry *pe = bestMatch(size, scale, mode, state, false);
|
QPixmapIconEngineEntry *pe = bestMatch(size, scale, mode, state);
|
||||||
if (pe)
|
if (pe)
|
||||||
pm = pe->pixmap;
|
pm = pe->pixmap;
|
||||||
else
|
else
|
||||||
@ -364,7 +393,7 @@ QSize QPixmapIconEngine::actualSize(const QSize &size, QIcon::Mode mode, QIcon::
|
|||||||
// does not proviode extra actual sizes not also provided by the 1x versions.
|
// does not proviode extra actual sizes not also provided by the 1x versions.
|
||||||
qreal scale = 1;
|
qreal scale = 1;
|
||||||
|
|
||||||
if (QPixmapIconEngineEntry *pe = bestMatch(size, scale, mode, state, true))
|
if (QPixmapIconEngineEntry *pe = bestMatch(size, scale, mode, state))
|
||||||
actualSize = pe->size;
|
actualSize = pe->size;
|
||||||
|
|
||||||
return adjustSize(size, actualSize);
|
return adjustSize(size, actualSize);
|
||||||
@ -438,10 +467,7 @@ void QPixmapIconEngine::addFile(const QString &fileName, const QSize &size, QIco
|
|||||||
pixmaps += QPixmapIconEngineEntry(abs, image, mode, state);
|
pixmaps += QPixmapIconEngineEntry(abs, image, mode, state);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Try to match size. If that fails, add a placeholder with the filename and empty pixmap for the size.
|
pixmaps += QPixmapIconEngineEntry(abs, size, mode, state);
|
||||||
while (imageReader.read(&image) && image.size() != size) {}
|
|
||||||
pixmaps += image.size() == size ?
|
|
||||||
QPixmapIconEngineEntry(abs, image, mode, state) : QPixmapIconEngineEntry(abs, size, mode, state);
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -77,7 +77,7 @@ public:
|
|||||||
void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) override;
|
void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) override;
|
||||||
QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) override;
|
QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) override;
|
||||||
QPixmap scaledPixmap(const QSize &size, QIcon::Mode mode, QIcon::State state, qreal scale) override;
|
QPixmap scaledPixmap(const QSize &size, QIcon::Mode mode, QIcon::State state, qreal scale) override;
|
||||||
QPixmapIconEngineEntry *bestMatch(const QSize &size, qreal scale, QIcon::Mode mode, QIcon::State state, bool sizeOnly);
|
QPixmapIconEngineEntry *bestMatch(const QSize &size, qreal scale, QIcon::Mode mode, QIcon::State state);
|
||||||
QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state) override;
|
QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state) override;
|
||||||
QList<QSize> availableSizes(QIcon::Mode mode, QIcon::State state) override;
|
QList<QSize> availableSizes(QIcon::Mode mode, QIcon::State state) override;
|
||||||
void addPixmap(const QPixmap &pixmap, QIcon::Mode mode, QIcon::State state) override;
|
void addPixmap(const QPixmap &pixmap, QIcon::Mode mode, QIcon::State state) override;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user