diff options
Diffstat (limited to 'src/gui/image/qmovie.cpp')
-rw-r--r-- | src/gui/image/qmovie.cpp | 147 |
1 files changed, 69 insertions, 78 deletions
diff --git a/src/gui/image/qmovie.cpp b/src/gui/image/qmovie.cpp index 25fce050a1..932326850a 100644 --- a/src/gui/image/qmovie.cpp +++ b/src/gui/image/qmovie.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 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 /*! \class QMovie @@ -45,9 +9,7 @@ \brief The QMovie class is a convenience class for playing movies with QImageReader. - This class is used to show simple animations without sound. If you want - to display video and media content, use the \l{Qt Multimedia} - multimedia framework instead. + This class is used to show simple animations without sound. First, create a QMovie object by passing either the name of a file or a pointer to a QIODevice containing an animated image format to QMovie's @@ -91,7 +53,7 @@ Call supportedFormats() for a list of formats that QMovie supports. - \sa QLabel, QImageReader, {Movie Example} + \sa QLabel, QImageReader */ /*! \enum QMovie::MovieState @@ -141,7 +103,6 @@ */ /*! \fn void QMovie::frameChanged(int frameNumber) - \since 4.1 This signal is emitted when the frame number has changed to \a frameNumber. You can call currentImage() or currentPixmap() to get a @@ -182,12 +143,14 @@ #include "qrect.h" #include "qelapsedtimer.h" #include "qtimer.h" -#include "qpair.h" #include "qmap.h" #include "qlist.h" #include "qbuffer.h" #include "qdir.h" +#include "qloggingcategory.h" +#include "private/qimage_p.h" #include "private/qobject_p.h" +#include "private/qproperty_p.h" #define QMOVIE_INVALID_DELAY -1 @@ -222,7 +185,7 @@ public: static inline QFrameInfo endMarker() { return QFrameInfo(true); } }; -Q_DECLARE_TYPEINFO(QFrameInfo, Q_MOVABLE_TYPE); +Q_DECLARE_TYPEINFO(QFrameInfo, Q_RELOCATABLE_TYPE); class QMoviePrivate : public QObjectPrivate { @@ -249,20 +212,24 @@ public: void _q_loadNextFrame(); void _q_loadNextFrame(bool starting); - QImageReader *reader; - int speed; - QMovie::MovieState movieState; + QImageReader *reader = nullptr; + + void setSpeed(int percentSpeed) { q_func()->setSpeed(percentSpeed); } + Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(QMoviePrivate, int, speed, &QMoviePrivate::setSpeed, 100) + + QMovie::MovieState movieState = QMovie::NotRunning; QRect frameRect; QPixmap currentPixmap; - int currentFrameNumber; - int nextFrameNumber; - int greatestFrameNumber; - int nextDelay; - int playCounter; - qint64 initialDevicePos; - QMovie::CacheMode cacheMode; - bool haveReadAll; - bool isFirstIteration; + int currentFrameNumber = -1; + int nextFrameNumber = 0; + int greatestFrameNumber = -1; + int nextDelay = 0; + int playCounter = -1; + qint64 initialDevicePos = 0; + Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(QMoviePrivate, QMovie::CacheMode, cacheMode, + QMovie::CacheNone) + bool haveReadAll = false; + bool isFirstIteration = true; QMap<int, QFrameInfo> frameMap; QString absoluteFilePath; @@ -272,10 +239,6 @@ public: /*! \internal */ QMoviePrivate::QMoviePrivate(QMovie *qq) - : reader(0), speed(100), movieState(QMovie::NotRunning), - currentFrameNumber(-1), nextFrameNumber(0), greatestFrameNumber(-1), - nextDelay(0), playCounter(-1), - cacheMode(QMovie::CacheNone), haveReadAll(false), isFirstIteration(true) { q_ptr = qq; nextImageTimer.setSingleShot(true); @@ -343,6 +306,19 @@ QFrameInfo QMoviePrivate::infoForFrame(int frameNumber) return QFrameInfo(); // Invalid } + // For an animated image format, the tradition is that QMovie calls read() + // until canRead() == false, because the number of frames may not be known + // in advance; but if we're abusing a multi-frame format as an animation, + // canRead() may remain true, and we need to stop after reading the maximum + // number of frames that the image provides. + const bool supportsAnimation = reader->supportsOption(QImageIOHandler::Animation); + const int stopAtFrame = supportsAnimation ? -1 : frameCount(); + + // For an animated image format, QImageIOHandler::nextImageDelay() should + // provide the time to wait until showing the next frame; but multi-frame + // formats are not expected to provide this value, so use 1000 ms by default. + const auto nextFrameDelay = [&]() { return supportsAnimation ? reader->nextImageDelay() : 1000; }; + if (cacheMode == QMovie::CacheNone) { if (frameNumber != currentFrameNumber+1) { // Non-sequential frame access @@ -372,8 +348,12 @@ QFrameInfo QMoviePrivate::infoForFrame(int frameNumber) } } } - if (reader->canRead()) { + qCDebug(lcImageIo, "CacheNone: read frame %d of %d", frameNumber, stopAtFrame); + if (stopAtFrame > 0 ? (frameNumber < stopAtFrame) : reader->canRead()) { // reader says we can read. Attempt to actually read image + // But if it's a non-animated multi-frame format and we know the frame count, stop there. + if (stopAtFrame > 0) + reader->jumpToImage(frameNumber); QImage anImage = reader->read(); if (anImage.isNull()) { // Reading image failed. @@ -381,7 +361,7 @@ QFrameInfo QMoviePrivate::infoForFrame(int frameNumber) } if (frameNumber > greatestFrameNumber) greatestFrameNumber = frameNumber; - return QFrameInfo(QPixmap::fromImage(std::move(anImage)), reader->nextImageDelay()); + return QFrameInfo(QPixmap::fromImage(std::move(anImage)), nextFrameDelay()); } else if (frameNumber != 0) { // We've read all frames now. Return an end marker haveReadAll = true; @@ -397,15 +377,19 @@ QFrameInfo QMoviePrivate::infoForFrame(int frameNumber) if (frameNumber > greatestFrameNumber) { // Frame hasn't been read from file yet. Try to do it for (int i = greatestFrameNumber + 1; i <= frameNumber; ++i) { - if (reader->canRead()) { + qCDebug(lcImageIo, "CacheAll: read frame %d of %d", frameNumber, stopAtFrame); + if (stopAtFrame > 0 ? (frameNumber < stopAtFrame) : reader->canRead()) { // reader says we can read. Attempt to actually read image + // But if it's a non-animated multi-frame format and we know the frame count, stop there. + if (stopAtFrame > 0) + reader->jumpToImage(frameNumber); QImage anImage = reader->read(); if (anImage.isNull()) { // Reading image failed. return QFrameInfo(); // Invalid } greatestFrameNumber = i; - QFrameInfo info(QPixmap::fromImage(std::move(anImage)), reader->nextImageDelay()); + QFrameInfo info(QPixmap::fromImage(std::move(anImage)), nextFrameDelay()); // Cache it! frameMap.insert(i, info); if (i == frameNumber) { @@ -463,11 +447,7 @@ bool QMoviePrivate::next() } // Image and delay OK, update internal state currentFrameNumber = nextFrameNumber++; - QSize scaledSize = reader->scaledSize(); - if (scaledSize.isValid() && (scaledSize != info.pixmap.size())) - currentPixmap = QPixmap::fromImage( info.pixmap.toImage().scaled(scaledSize) ); - else - currentPixmap = info.pixmap; + currentPixmap = info.pixmap; if (!speed) return true; @@ -930,7 +910,12 @@ void QMovie::setSpeed(int percentSpeed) Q_D(QMovie); if (!d->speed && d->movieState == Running) d->nextImageTimer.start(nextFrameDelay()); - d->speed = percentSpeed; + if (percentSpeed != d->speed) { + d->speed = percentSpeed; + d->speed.notify(); + } else { + d->speed.removeBindingUnlessInWrapper(); + } } int QMovie::speed() const @@ -939,6 +924,12 @@ int QMovie::speed() const return d->speed; } +QBindable<int> QMovie::bindableSpeed() +{ + Q_D(QMovie); + return &d->speed; +} + /*! Starts the movie. QMovie will enter \l Running state, and start emitting updated() and resized() as the movie progresses. @@ -980,8 +971,6 @@ void QMovie::stop() } /*! - \since 4.1 - Returns the scaled size of frames. \sa QImageReader::scaledSize() @@ -993,8 +982,6 @@ QSize QMovie::scaledSize() } /*! - \since 4.1 - Sets the scaled frame size to \a size. \sa QImageReader::setScaledSize() @@ -1006,8 +993,6 @@ void QMovie::setScaledSize(const QSize &size) } /*! - \since 4.1 - Returns the list of image formats supported by QMovie. \sa QImageReader::supportedImageFormats() @@ -1024,7 +1009,7 @@ QList<QByteArray> QMovie::supportedFormats() return !QImageReader(&buffer, format).supportsOption(QImageIOHandler::Animation); }; - list.erase(std::remove_if(list.begin(), list.end(), doesntSupportAnimation), list.end()); + list.removeIf(doesntSupportAnimation); return list; } @@ -1061,6 +1046,12 @@ void QMovie::setCacheMode(CacheMode cacheMode) d->cacheMode = cacheMode; } +QBindable<QMovie::CacheMode> QMovie::bindableCacheMode() +{ + Q_D(QMovie); + return &d->cacheMode; +} + QT_END_NAMESPACE #include "moc_qmovie.cpp" |