1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtQuick module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qquickimageprovider.h"
41
42#include "qquickimageprovider_p.h"
43#include "qquickpixmapcache_p.h"
44#include <QtQuick/private/qsgcontext_p.h>
45#include <private/qqmlglobal_p.h>
46#include <QtGui/qcolorspace.h>
47
48QT_BEGIN_NAMESPACE
49
50/*!
51 \class QQuickTextureFactory
52 \since 5.0
53 \brief The QQuickTextureFactory class provides an interface for loading custom textures from QML.
54 \inmodule QtQuick
55
56 The purpose of the texture factory is to provide a placeholder for a image
57 data that can be converted into an OpenGL texture.
58
59 Creating a texture directly is not possible as there is rarely an OpenGL context
60 available in the thread that is responsible for loading the image data.
61*/
62
63/*!
64 Constructs a texture factory. Since QQuickTextureFactory is abstract, it
65 cannot be instantiated directly.
66*/
67
68QQuickTextureFactory::QQuickTextureFactory()
69{
70}
71
72/*!
73 Destroys the texture factory.
74*/
75
76QQuickTextureFactory::~QQuickTextureFactory()
77{
78}
79
80/*!
81 \fn int QQuickTextureFactory::textureByteCount() const
82
83 Returns the number of bytes of memory the texture consumes.
84*/
85
86/*!
87 \fn QImage QQuickTextureFactory::image() const
88
89 Returns an image version of this texture.
90
91 The lifespan of the returned image is unknown, so the implementation should
92 return a self contained QImage, not make use of the QImage(uchar *, ...)
93 constructor.
94
95 This function is not commonly used and is expected to be slow.
96 */
97
98QImage QQuickTextureFactory::image() const
99{
100 return QImage();
101}
102
103/*!
104 Returns a QQuickTextureFactory holding the given \a image.
105
106 This is typically used as a helper in QQuickImageResponse::textureFactory.
107
108 \since 5.6
109 */
110
111QQuickTextureFactory *QQuickTextureFactory::textureFactoryForImage(const QImage &image)
112{
113 if (image.isNull())
114 return nullptr;
115 QQuickTextureFactory *texture = QSGContext::createTextureFactoryFromImage(image);
116 if (texture)
117 return texture;
118 return new QQuickDefaultTextureFactory(image);
119}
120
121
122
123/*!
124 \fn QSGTexture *QQuickTextureFactory::createTexture(QQuickWindow *window) const
125
126 This function is called on the scene graph rendering thread to create a QSGTexture
127 instance from the factory. \a window provides the context which this texture is
128 created in.
129
130 QML will internally cache the returned texture as needed. Each call to this
131 function should return a unique instance.
132
133 The OpenGL context used for rendering is bound when this function is called.
134 */
135
136/*!
137 \fn QSize QQuickTextureFactory::textureSize() const
138
139 Returns the size of the texture. This function will be called from arbitrary threads
140 and should not rely on an OpenGL context bound.
141 */
142
143
144/*!
145 \class QQuickImageResponse
146 \since 5.6
147 \brief The QQuickImageResponse class provides an interface for asynchronous image loading in QQuickAsyncImageProvider.
148 \inmodule QtQuick
149
150 The purpose of an image response is to provide a way for image provider jobs to be executed
151 in an asynchronous way.
152
153 Responses are deleted via \l deleteLater once the finished() signal has been emitted.
154 If you are using QRunnable as base for your QQuickImageResponse
155 ensure automatic deletion is disabled.
156
157 See the \l {imageresponseprovider}{Image Response Provider Example} for a complete implementation.
158
159 \sa QQuickImageProvider
160*/
161
162/*!
163 Constructs the image response
164*/
165QQuickImageResponse::QQuickImageResponse()
166 : QObject(*(new QQuickImageResponsePrivate))
167{
168 qmlobject_connect(this, QQuickImageResponse, SIGNAL(finished()),
169 this, QQuickImageResponse, SLOT(_q_finished()));
170}
171
172/*!
173 Destructs the image response
174*/
175QQuickImageResponse::~QQuickImageResponse()
176{
177}
178
179/*!
180 Returns the error string for the job execution. An empty string means no error.
181*/
182QString QQuickImageResponse::errorString() const
183{
184 return QString();
185}
186
187/*!
188 This method is used to communicate that the response is no longer required by the engine.
189
190 It may be reimplemented to cancel a request in the provider side, however, it is not mandatory.
191
192 A cancelled QQuickImageResponse still needs to emit finished() so that the
193 engine may clean up the QQuickImageResponse.
194
195 \note finished() should not be emitted until the response is complete,
196 regardless of whether or not cancel() was called. If it is called prematurely,
197 the engine may destroy the response while it is still active, leading to a crash.
198*/
199void QQuickImageResponse::cancel()
200{
201}
202
203/*!
204 \fn void QQuickImageResponse::finished()
205
206 Signals that the job execution has finished (be it successfully, because an
207 error happened or because it was cancelled).
208
209 \note Emission of this signal must be the final action the response performs:
210 once the signal is received, the response will subsequently be destroyed by
211 the engine.
212 */
213
214/*!
215 \fn QQuickTextureFactory *QQuickImageResponse::textureFactory() const
216
217 Returns the texture factory for the job. You can use QQuickTextureFactory::textureFactoryForImage
218 if your provider works with QImage. The engine takes ownership of the returned QQuickTextureFactory.
219
220 \note This method will be called only when needed. For example, it may not be called if there is an
221 error or the job is cancelled. Therefore, allocate the QQuickTextureFactory instance only in this
222 method or otherwise ensure its deletion.
223 */
224
225
226/*!
227 \class QQuickImageProvider
228 \since 5.0
229 \inmodule QtQuick
230 \brief The QQuickImageProvider class provides an interface for supporting pixmaps and threaded image requests in QML.
231
232 QQuickImageProvider is used to provide advanced image loading features
233 in QML applications. It allows images in QML to be:
234
235 \list
236 \li Loaded using QPixmaps rather than actual image files
237 \li Loaded asynchronously in a separate thread
238 \endlist
239
240 To specify that an image should be loaded by an image provider, use the
241 \b {"image:"} scheme for the URL source of the image, followed by the
242 identifiers of the image provider and the requested image. For example:
243
244 \qml
245 Image { source: "image://myimageprovider/image.png" }
246 \endqml
247
248 This specifies that the image should be loaded by the image provider named
249 "myimageprovider", and the image to be loaded is named "image.png". The QML engine
250 invokes the appropriate image provider according to the providers that have
251 been registered through QQmlEngine::addImageProvider().
252
253 Note that the identifiers are case-insensitive, but the rest of the URL will be passed on with
254 preserved case. For example, the below snippet would still specify that the image is loaded by the
255 image provider named "myimageprovider", but it would request a different image than the above snippet
256 ("Image.png" instead of "image.png").
257 \qml
258 Image { source: "image://MyImageProvider/Image.png" }
259 \endqml
260
261 If you want the rest of the URL to be case insensitive, you will have to take care
262 of that yourself inside your image provider.
263
264 \section2 An Example
265
266 Here are two images. Their \c source values indicate they should be loaded by
267 an image provider named "colors", and the images to be loaded are "yellow"
268 and "red", respectively:
269
270 \snippet imgprovider/imageprovider-example.qml 0
271
272 When these images are loaded by QML, it looks for a matching image provider
273 and calls its requestImage() or requestPixmap() method (depending on its
274 imageType()) to load the image. The method is called with the \c id
275 parameter set to "yellow" for the first image, and "red" for the second.
276
277 Here is an image provider implementation that can load the images
278 requested by the above QML. This implementation dynamically
279 generates QPixmap images that are filled with the requested color:
280
281 \snippet imgprovider/imageprovider.cpp 0
282
283 To make this provider accessible to QML, it is registered with the QML engine
284 with a "colors" identifier:
285
286 \snippet imgprovider/imageprovider.cpp 1
287 \codeline
288 \snippet imgprovider/imageprovider.cpp 2
289
290 Now the images can be successfully loaded in QML:
291
292 \image imageprovider.png
293
294 See the \l {imageprovider}{Image Provider Example} for the complete implementation.
295 Note that the example registers the provider via a \l{QQmlEngineExtensionPlugin}{plugin}
296 instead of registering it in the application \c main() function as shown above.
297
298
299 \section2 Asynchronous Image Loading
300
301 Image providers that support QImage or Texture loading automatically include support
302 for asychronous loading of images. To enable asynchronous loading for an
303 image source, set the \c asynchronous property to \c true for the relevant
304 \l Image or \l BorderImage object. When this is enabled,
305 the image request to the provider is run in a low priority thread,
306 allowing image loading to be executed in the background, and reducing the
307 performance impact on the user interface.
308
309 To force asynchronous image loading, even for image sources that do not
310 have the \c asynchronous property set to \c true, you may pass the
311 \c QQmlImageProviderBase::ForceAsynchronousImageLoading flag to the image
312 provider constructor. This ensures that all image requests for the
313 provider are handled in a separate thread.
314
315 Asynchronous loading for image providers that provide QPixmap is only supported
316 in platforms that have the ThreadedPixmaps feature, in platforms where
317 pixmaps can only be created in the main thread (i.e. ThreadedPixmaps is not supported)
318 if \l {Image::}{asynchronous} is set to \c true, the value is ignored
319 and the image is loaded synchronously.
320
321 Asynchronous image loading for providers of type other than ImageResponse are
322 executed on a single thread per engine basis. That means that a slow image provider
323 will block the loading of any other request. To avoid that we suggest using QQuickAsyncImageProvider
324 and implement threading on the provider side via a \c QThreadPool or similar.
325 See the \l {imageresponseprovider}{Image Response Provider Example} for a complete implementation.
326
327
328 \section2 Image Caching
329
330 Images returned by a QQuickImageProvider are automatically cached,
331 similar to any image loaded by the QML engine. When an image with a
332 "image://" prefix is loaded from cache, requestImage() and requestPixmap()
333 will not be called for the relevant image provider. If an image should
334 always be fetched from the image provider, and should not be cached at
335 all, set the \c cache property to \c false for the relevant \l Image
336 or \l BorderImage object.
337
338 \sa QQmlEngine::addImageProvider()
339*/
340
341/*!
342 Creates an image provider that will provide images of the given \a type and
343 behave according to the given \a flags.
344*/
345QQuickImageProvider::QQuickImageProvider(ImageType type, Flags flags)
346 : d(new QQuickImageProviderPrivate)
347{
348 d->type = type;
349 d->flags = flags;
350 d->isProviderWithOptions = false;
351}
352
353/*!
354 Destroys the QQuickImageProvider
355
356 \note The destructor of your derived class need to be thread safe.
357*/
358QQuickImageProvider::~QQuickImageProvider()
359{
360 delete d;
361}
362
363/*!
364 Returns the image type supported by this provider.
365*/
366QQuickImageProvider::ImageType QQuickImageProvider::imageType() const
367{
368 return d->type;
369}
370
371/*!
372 Returns the flags set for this provider.
373*/
374QQuickImageProvider::Flags QQuickImageProvider::flags() const
375{
376 return d->flags;
377}
378
379/*!
380 Implement this method to return the image with \a id. The default
381 implementation returns an empty image.
382
383 The \a id is the requested image source, with the "image:" scheme and
384 provider identifier removed. For example, if the image \l{Image::}{source}
385 was "image://myprovider/icons/home", the given \a id would be "icons/home".
386
387 The \a requestedSize corresponds to the \l {Image::sourceSize} requested by
388 an Image item. If \a requestedSize is a valid size, the image
389 returned should be of that size.
390
391 In all cases, \a size must be set to the original size of the image. This
392 is used to set the \l {Item::}{width} and \l {Item::}{height} of the
393 relevant \l Image if these values have not been set explicitly.
394
395 \note this method may be called by multiple threads, so ensure the
396 implementation of this method is reentrant.
397*/
398QImage QQuickImageProvider::requestImage(const QString &id, QSize *size, const QSize& requestedSize)
399{
400 Q_UNUSED(id);
401 Q_UNUSED(size);
402 Q_UNUSED(requestedSize);
403 if (d->type == Image)
404 qWarning(msg: "ImageProvider supports Image type but has not implemented requestImage()");
405 return QImage();
406}
407
408/*!
409 Implement this method to return the pixmap with \a id. The default
410 implementation returns an empty pixmap.
411
412 The \a id is the requested image source, with the "image:" scheme and
413 provider identifier removed. For example, if the image \l{Image::}{source}
414 was "image://myprovider/icons/home", the given \a id would be "icons/home".
415
416 The \a requestedSize corresponds to the \l {Image::sourceSize} requested by
417 an Image item. If \a requestedSize is a valid size, the image
418 returned should be of that size.
419
420 In all cases, \a size must be set to the original size of the image. This
421 is used to set the \l {Item::}{width} and \l {Item::}{height} of the
422 relevant \l Image if these values have not been set explicitly.
423
424 \note this method may be called by multiple threads, so ensure the
425 implementation of this method is reentrant.
426*/
427QPixmap QQuickImageProvider::requestPixmap(const QString &id, QSize *size, const QSize& requestedSize)
428{
429 Q_UNUSED(id);
430 Q_UNUSED(size);
431 Q_UNUSED(requestedSize);
432 if (d->type == Pixmap)
433 qWarning(msg: "ImageProvider supports Pixmap type but has not implemented requestPixmap()");
434 return QPixmap();
435}
436
437
438/*!
439 Implement this method to return the texture with \a id. The default
440 implementation returns \nullptr.
441
442 The \a id is the requested image source, with the "image:" scheme and
443 provider identifier removed. For example, if the image \l{Image::}{source}
444 was "image://myprovider/icons/home", the given \a id would be "icons/home".
445
446 The \a requestedSize corresponds to the \l {Image::sourceSize} requested by
447 an Image item. If \a requestedSize is a valid size, the image
448 returned should be of that size.
449
450 In all cases, \a size must be set to the original size of the image. This
451 is used to set the \l {Item::}{width} and \l {Item::}{height} of the
452 relevant \l Image if these values have not been set explicitly.
453
454 \note this method may be called by multiple threads, so ensure the
455 implementation of this method is reentrant.
456*/
457
458QQuickTextureFactory *QQuickImageProvider::requestTexture(const QString &id, QSize *size, const QSize &requestedSize)
459{
460 Q_UNUSED(id);
461 Q_UNUSED(size);
462 Q_UNUSED(requestedSize);
463 if (d->type == Texture)
464 qWarning(msg: "ImageProvider supports Texture type but has not implemented requestTexture()");
465 return nullptr;
466}
467
468/*!
469 \class QQuickAsyncImageProvider
470 \since 5.6
471 \inmodule QtQuick
472 \brief The QQuickAsyncImageProvider class provides an interface for for asynchronous control of QML image requests.
473
474 See the \l {imageresponseprovider}{Image Response Provider Example} for a complete implementation.
475
476 \sa QQuickImageProvider
477*/
478QQuickAsyncImageProvider::QQuickAsyncImageProvider()
479 : QQuickImageProvider(ImageResponse, ForceAsynchronousImageLoading)
480 , d(nullptr) // just as a placeholder in case we need it for the future
481{
482 Q_UNUSED(d);
483}
484
485QQuickAsyncImageProvider::~QQuickAsyncImageProvider()
486{
487}
488
489/*!
490 \fn QQuickImageResponse *QQuickAsyncImageProvider::requestImageResponse(const QString &id, const QSize &requestedSize)
491
492 Implement this method to return the job that will provide the texture with \a id.
493
494 The \a id is the requested image source, with the "image:" scheme and
495 provider identifier removed. For example, if the image \l{Image::}{source}
496 was "image://myprovider/icons/home", the given \a id would be "icons/home".
497
498 The \a requestedSize corresponds to the \l {Image::sourceSize} requested by
499 an Image item. If \a requestedSize is a valid size, the image
500 returned should be of that size.
501
502 \note this method may be called by multiple threads, so ensure the
503 implementation of this method is reentrant.
504*/
505
506
507class QQuickImageProviderOptionsPrivate : public QSharedData
508{
509public:
510 QQuickImageProviderOptionsPrivate()
511 {
512 }
513
514 QColorSpace targetColorSpace;
515 QQuickImageProviderOptions::AutoTransform autoTransform = QQuickImageProviderOptions::UsePluginDefaultTransform;
516 bool preserveAspectRatioCrop = false;
517 bool preserveAspectRatioFit = false;
518};
519
520/*!
521 \class QQuickImageProviderOptions
522 \brief The QQuickImageProviderOptions class provides options for QQuickImageProviderWithOptions image requests.
523 \inmodule QtQuick
524 \internal
525
526 \sa QQuickImageProviderWithOptions
527*/
528
529/*!
530 \enum QQuickImageProviderOptions::AutoTransform
531
532 Whether the image provider should apply transformation metadata on read().
533
534 \value UsePluginDefaultTransform Image provider should do its default behavior on whether applying transformation metadata on read or not
535 \value ApplyTransform Image provider should apply transformation metadata on read
536 \value DoNotApplyTransform Image provider should not apply transformation metadata on read
537*/
538
539QQuickImageProviderOptions::QQuickImageProviderOptions()
540 : d(new QQuickImageProviderOptionsPrivate())
541{
542}
543
544QQuickImageProviderOptions::~QQuickImageProviderOptions()
545{
546}
547
548QQuickImageProviderOptions::QQuickImageProviderOptions(const QQuickImageProviderOptions &other)
549 : d(other.d)
550{
551}
552
553QQuickImageProviderOptions& QQuickImageProviderOptions::operator=(const QQuickImageProviderOptions &other)
554{
555 d = other.d;
556 return *this;
557}
558
559bool QQuickImageProviderOptions::operator==(const QQuickImageProviderOptions &other) const
560{
561 return d->autoTransform == other.d->autoTransform &&
562 d->preserveAspectRatioCrop == other.d->preserveAspectRatioCrop &&
563 d->preserveAspectRatioFit == other.d->preserveAspectRatioFit &&
564 d->targetColorSpace == other.d->targetColorSpace;
565}
566
567/*!
568 Returns whether the image provider should apply transformation metadata on read().
569*/
570QQuickImageProviderOptions::AutoTransform QQuickImageProviderOptions::autoTransform() const
571{
572 return d->autoTransform;
573}
574
575void QQuickImageProviderOptions::setAutoTransform(QQuickImageProviderOptions::AutoTransform autoTransform)
576{
577 d->autoTransform = autoTransform;
578}
579
580/*!
581 Returns whether the image request is for a PreserveAspectCrop Image.
582 This allows the provider to better optimize the size of the returned image.
583*/
584bool QQuickImageProviderOptions::preserveAspectRatioCrop() const
585{
586 return d->preserveAspectRatioCrop;
587}
588
589void QQuickImageProviderOptions::setPreserveAspectRatioCrop(bool preserveAspectRatioCrop)
590{
591 d->preserveAspectRatioCrop = preserveAspectRatioCrop;
592}
593
594/*!
595 Returns whether the image request is for a PreserveAspectFit Image.
596 This allows the provider to better optimize the size of the returned image.
597*/
598bool QQuickImageProviderOptions::preserveAspectRatioFit() const
599{
600 return d->preserveAspectRatioFit;
601}
602
603void QQuickImageProviderOptions::setPreserveAspectRatioFit(bool preserveAspectRatioFit)
604{
605 d->preserveAspectRatioFit = preserveAspectRatioFit;
606}
607
608/*!
609 Returns the color space the image provider should return the image in.
610*/
611QColorSpace QQuickImageProviderOptions::targetColorSpace() const
612{
613 return d->targetColorSpace;
614}
615
616void QQuickImageProviderOptions::setTargetColorSpace(const QColorSpace &colorSpace)
617{
618 d->targetColorSpace = colorSpace;
619}
620
621QQuickImageProviderWithOptions::QQuickImageProviderWithOptions(ImageType type, Flags flags)
622 : QQuickAsyncImageProvider()
623{
624 QQuickImageProvider::d->type = type;
625 QQuickImageProvider::d->flags = flags;
626 QQuickImageProvider::d->isProviderWithOptions = true;
627}
628
629QImage QQuickImageProviderWithOptions::requestImage(const QString &id, QSize *size, const QSize& requestedSize)
630{
631 return requestImage(id, size, requestedSize, options: QQuickImageProviderOptions());
632}
633
634QPixmap QQuickImageProviderWithOptions::requestPixmap(const QString &id, QSize *size, const QSize& requestedSize)
635{
636 return requestPixmap(id, size, requestedSize, options: QQuickImageProviderOptions());
637}
638
639QQuickTextureFactory *QQuickImageProviderWithOptions::requestTexture(const QString &id, QSize *size, const QSize &requestedSize)
640{
641 return requestTexture(id, size, requestedSize, options: QQuickImageProviderOptions());
642}
643
644QImage QQuickImageProviderWithOptions::requestImage(const QString &id, QSize *size, const QSize& requestedSize, const QQuickImageProviderOptions &options)
645{
646 Q_UNUSED(options);
647 return QQuickAsyncImageProvider::requestImage(id, size, requestedSize);
648}
649
650QPixmap QQuickImageProviderWithOptions::requestPixmap(const QString &id, QSize *size, const QSize& requestedSize, const QQuickImageProviderOptions &options)
651{
652 Q_UNUSED(options);
653 return QQuickAsyncImageProvider::requestPixmap(id, size, requestedSize);
654}
655
656QQuickTextureFactory *QQuickImageProviderWithOptions::requestTexture(const QString &id, QSize *size, const QSize &requestedSize, const QQuickImageProviderOptions &options)
657{
658 Q_UNUSED(options);
659 return QQuickAsyncImageProvider::requestTexture(id, size, requestedSize);
660}
661
662QQuickImageResponse *QQuickImageProviderWithOptions::requestImageResponse(const QString &id, const QSize &requestedSize)
663{
664 Q_UNUSED(id);
665 Q_UNUSED(requestedSize);
666 if (imageType() == ImageResponse)
667 qWarning(msg: "ImageProvider is of ImageResponse type but has not implemented requestImageResponse()");
668 return nullptr;
669}
670
671QQuickImageResponse *QQuickImageProviderWithOptions::requestImageResponse(const QString &id, const QSize &requestedSize, const QQuickImageProviderOptions &options)
672{
673 Q_UNUSED(options);
674 return requestImageResponse(id, requestedSize);
675}
676
677/*!
678 Returns the recommended scaled image size for loading and storage. This is
679 calculated according to the native pixel size of the image \a originalSize,
680 the requested sourceSize \a requestedSize, the image file format \a format,
681 and \a options. If the calculation otherwise concludes that scaled loading
682 is not recommended, an invalid size is returned.
683*/
684QSize QQuickImageProviderWithOptions::loadSize(const QSize &originalSize, const QSize &requestedSize, const QByteArray &format, const QQuickImageProviderOptions &options)
685{
686 QSize res;
687 if ((requestedSize.width() <= 0 && requestedSize.height() <= 0) || originalSize.isEmpty())
688 return res;
689
690 const bool preserveAspectCropOrFit = options.preserveAspectRatioCrop() || options.preserveAspectRatioFit();
691 const bool formatIsScalable = (format == "svg" || format == "svgz" || format == "pdf");
692
693 if (!preserveAspectCropOrFit && formatIsScalable && !requestedSize.isEmpty())
694 return requestedSize;
695
696 qreal ratio = 0.0;
697 if (requestedSize.width() && (preserveAspectCropOrFit || formatIsScalable ||
698 requestedSize.width() < originalSize.width())) {
699 ratio = qreal(requestedSize.width()) / originalSize.width();
700 }
701 if (requestedSize.height() && (preserveAspectCropOrFit || formatIsScalable ||
702 requestedSize.height() < originalSize.height())) {
703 qreal hr = qreal(requestedSize.height()) / originalSize.height();
704 if (ratio == 0.0)
705 ratio = hr;
706 else if (!preserveAspectCropOrFit && (hr < ratio))
707 ratio = hr;
708 else if (preserveAspectCropOrFit && (hr > ratio))
709 ratio = hr;
710 }
711 if (ratio > 0.0) {
712 res.setHeight(qRound(d: originalSize.height() * ratio));
713 res.setWidth(qRound(d: originalSize.width() * ratio));
714 }
715 return res;
716}
717
718QQuickImageProviderWithOptions *QQuickImageProviderWithOptions::checkedCast(QQuickImageProvider *provider)
719{
720 if (provider && provider->d && provider->d->isProviderWithOptions)
721 return static_cast<QQuickImageProviderWithOptions *>(provider);
722
723 return nullptr;
724}
725
726QT_END_NAMESPACE
727
728#include "moc_qquickimageprovider.cpp"
729

source code of qtdeclarative/src/quick/util/qquickimageprovider.cpp