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