diff options
Diffstat (limited to 'src/gui/image/qmovie.cpp')
-rw-r--r-- | src/gui/image/qmovie.cpp | 141 |
1 files changed, 70 insertions, 71 deletions
diff --git a/src/gui/image/qmovie.cpp b/src/gui/image/qmovie.cpp index 79019d0fdf..0d13639d35 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 @@ -182,17 +144,20 @@ #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/qobject_p.h" +#include "private/qproperty_p.h" #define QMOVIE_INVALID_DELAY -1 QT_BEGIN_NAMESPACE +Q_DECLARE_LOGGING_CATEGORY(lcImageIo) + class QFrameInfo { public: @@ -222,7 +187,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 +214,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 +241,6 @@ public: /*! \internal */ QMoviePrivate::QMoviePrivate(QMovie *qq) - : reader(nullptr), 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 +308,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 +350,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 +363,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 +379,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 +449,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 +912,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 +926,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. @@ -1024,7 +1017,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 +1054,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" |