Revision control
++ // Copyright (C) 2017 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
++ // Qt-Security score:significant reason:default
++
++ #include <qsharedimageprovider_p.h>
++ #include <private/qquickpixmap_p.h>
++ #include <private/qimage_p.h>
++ #include <QImageReader>
++ #include <QFileInfo>
++ #include <QDir>
++
++ Q_DECLARE_METATYPE(QQuickImageProviderOptions)
++
++ QT_BEGIN_NAMESPACE
++
++ QuickSharedImageLoader::QuickSharedImageLoader(QObject *parent) : QSharedImageLoader(parent) {}
++
++ QImage QuickSharedImageLoader::loadFile(const QString &path, ImageParameters *params)
++ {
++ QImageReader imgio(path);
++ QSize realSize = imgio.size();
++ QSize requestSize;
++ QQuickImageProviderOptions options;
++ if (params) {
++ requestSize = params->value(RequestedSize).toSize();
++ options = params->value(ProviderOptions).value<QQuickImageProviderOptions>();
++ }
++
++ QSize scSize = QQuickImageProviderWithOptions::loadSize(imgio.size(), requestSize, imgio.format(), options);
++
++ if (scSize.isValid())
++ imgio.setScaledSize(scSize);
++
++ QImage image;
++ if (imgio.read(&image)) {
++ if (realSize.isEmpty())
++ realSize = image.size();
++ // Make sure we have acceptable format for texture uploader, or it will convert & lose sharing
++ // This mimics the testing & conversion normally done by the quick pixmapcache & texturefactory
++ if (image.format() != QImage::Format_RGB32 && image.format() != QImage::Format_ARGB32_Premultiplied) {
++ QImage::Format newFmt = QImage::Format_RGB32;
++ if (image.hasAlphaChannel() && image.data_ptr()->checkForAlphaPixels())
++ newFmt = QImage::Format_ARGB32_Premultiplied;
++ qCDebug(lcSharedImage) << "Convert on load from format" << image.format() << "to" << newFmt;
++ image = image.convertToFormat(newFmt);
++ }
++ }
++
++ if (params && params->size() > OriginalSize)
++ params->replace(OriginalSize, realSize);
++
++ return image;
++ }
++
++ QString QuickSharedImageLoader::key(const QString &path, ImageParameters *params)
++ {
++ QSize reqSz;
++ QQuickImageProviderOptions opts;
++ if (params) {
++ reqSz = params->value(RequestedSize).toSize();
++ opts = params->value(ProviderOptions).value<QQuickImageProviderOptions>();
++ }
++ if (!reqSz.isValid())
++ return path;
++ int aspect = opts.preserveAspectRatioCrop() || opts.preserveAspectRatioFit() ? 1 : 0;
++
++ QString key = path + QStringLiteral("_%1x%2_%3").arg(reqSz.width()).arg(reqSz.height()).arg(aspect);
++ qCDebug(lcSharedImage) << "KEY:" << key;
++ return key;
++ }
++
++ SharedImageProvider::SharedImageProvider()
++ : QQuickImageProviderWithOptions(QQuickImageProvider::Image), loader(new QuickSharedImageLoader)
++ {
++ }
++
++ QImage SharedImageProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize, const QQuickImageProviderOptions &options)
++ {
++ QFileInfo fi(QDir::root(), id);
++ QString path = fi.canonicalFilePath();
++ if (path.isEmpty())
++ return QImage();
++
++ QSharedImageLoader::ImageParameters params(QuickSharedImageLoader::NumImageParameters);
++ params[QuickSharedImageLoader::RequestedSize].setValue(requestedSize);
++ params[QuickSharedImageLoader::ProviderOptions].setValue(options);
++
++ QImage img = loader->load(path, ¶ms);
++ if (img.isNull()) {
++ // May be sharing problem, fall back to normal local load
++ img = loader->loadFile(path, ¶ms);
++ if (!img.isNull())
++ qCWarning(lcSharedImage) << "Sharing problem; loading" << id << "unshared";
++ }
++
++ //... QSize realSize = params.value(QSharedImageLoader::OriginalSize).toSize();
++ // quickpixmapcache's readImage() reports back the original size, prior to requestedSize scaling, in the *size
++ // parameter. That value is currently ignored by quick however, which only cares about the present size of the
++ // returned image. So handling and sharing of info on pre-scaled size is currently not implemented.
++ if (size) {
++ *size = img.size();
++ }
++
++ return img;
++ }
++
++ QT_END_NAMESPACE
++
++ #include "moc_qsharedimageprovider_p.cpp"