PageRenderTime 45ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/src/qt/qtbase/src/gui/image/qmovie.cpp

https://gitlab.com/x33n/phantomjs
C++ | 1024 lines | 492 code | 83 blank | 449 comment | 85 complexity | f01afab9430082f082c092c5f9748237 MD5 | raw file
  1. /****************************************************************************
  2. **
  3. ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
  4. ** Contact: http://www.qt-project.org/legal
  5. **
  6. ** This file is part of the QtGui 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 Digia. For licensing terms and
  14. ** conditions see http://qt.digia.com/licensing. For further information
  15. ** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
  20. ** Foundation and appearing in the file LICENSE.LGPL included in the
  21. ** packaging of this file. Please review the following information to
  22. ** ensure the GNU Lesser General Public License version 2.1 requirements
  23. ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
  24. **
  25. ** In addition, as a special exception, Digia gives you certain additional
  26. ** rights. These rights are described in the Digia Qt LGPL Exception
  27. ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
  28. **
  29. ** GNU General Public License Usage
  30. ** Alternatively, this file may be used under the terms of the GNU
  31. ** General Public License version 3.0 as published by the Free Software
  32. ** Foundation and appearing in the file LICENSE.GPL included in the
  33. ** packaging of this file. Please review the following information to
  34. ** ensure the GNU General Public License version 3.0 requirements will be
  35. ** met: http://www.gnu.org/copyleft/gpl.html.
  36. **
  37. **
  38. ** $QT_END_LICENSE$
  39. **
  40. ****************************************************************************/
  41. /*!
  42. \class QMovie
  43. \inmodule QtGui
  44. \brief The QMovie class is a convenience class for playing movies
  45. with QImageReader.
  46. This class is used to show simple animations without sound. If you want
  47. to display video and media content, use the \l{Qt Multimedia}
  48. multimedia framework instead.
  49. First, create a QMovie object by passing either the name of a file or a
  50. pointer to a QIODevice containing an animated image format to QMovie's
  51. constructor. You can call isValid() to check if the image data is valid,
  52. before starting the movie. To start the movie, call start(). QMovie will
  53. enter \l Running state, and emit started() and stateChanged(). To get the
  54. current state of the movie, call state().
  55. To display the movie in your application, you can pass your QMovie object
  56. to QLabel::setMovie(). Example:
  57. \snippet code/src_gui_image_qmovie.cpp 0
  58. Whenever a new frame is available in the movie, QMovie will emit
  59. updated(). If the size of the frame changes, resized() is emitted. You can
  60. call currentImage() or currentPixmap() to get a copy of the current
  61. frame. When the movie is done, QMovie emits finished(). If any error
  62. occurs during playback (i.e, the image file is corrupt), QMovie will emit
  63. error().
  64. You can control the speed of the movie playback by calling setSpeed(),
  65. which takes the percentage of the original speed as an argument. Pause the
  66. movie by calling setPaused(true). QMovie will then enter \l Paused state
  67. and emit stateChanged(). If you call setPaused(false), QMovie will reenter
  68. \l Running state and start the movie again. To stop the movie, call
  69. stop().
  70. Certain animation formats allow you to set the background color. You can
  71. call setBackgroundColor() to set the color, or backgroundColor() to
  72. retrieve the current background color.
  73. currentFrameNumber() returns the sequence number of the current frame. The
  74. first frame in the animation has the sequence number 0. frameCount()
  75. returns the total number of frames in the animation, if the image format
  76. supports this. You can call loopCount() to get the number of times the
  77. movie should loop before finishing. nextFrameDelay() returns the number of
  78. milliseconds the current frame should be displayed.
  79. QMovie can be instructed to cache frames of an animation by calling
  80. setCacheMode().
  81. Call supportedFormats() for a list of formats that QMovie supports.
  82. \sa QLabel, QImageReader, {Movie Example}
  83. */
  84. /*! \enum QMovie::MovieState
  85. This enum describes the different states of QMovie.
  86. \value NotRunning The movie is not running. This is QMovie's initial
  87. state, and the state it enters after stop() has been called or the movie
  88. is finished.
  89. \value Paused The movie is paused, and QMovie stops emitting updated() or
  90. resized(). This state is entered after calling pause() or
  91. setPaused(true). The current frame number it kept, and the movie will
  92. continue with the next frame when unpause() or setPaused(false) is called.
  93. \value Running The movie is running.
  94. */
  95. /*! \enum QMovie::CacheMode
  96. This enum describes the different cache modes of QMovie.
  97. \value CacheNone No frames are cached (the default).
  98. \value CacheAll All frames are cached.
  99. */
  100. /*! \fn void QMovie::started()
  101. This signal is emitted after QMovie::start() has been called, and QMovie
  102. has entered QMovie::Running state.
  103. */
  104. /*! \fn void QMovie::resized(const QSize &size)
  105. This signal is emitted when the current frame has been resized to \a
  106. size. This effect is sometimes used in animations as an alternative to
  107. replacing the frame. You can call currentImage() or currentPixmap() to get a
  108. copy of the updated frame.
  109. */
  110. /*! \fn void QMovie::updated(const QRect &rect)
  111. This signal is emitted when the rect \a rect in the current frame has been
  112. updated. You can call currentImage() or currentPixmap() to get a copy of the
  113. updated frame.
  114. */
  115. /*! \fn void QMovie::frameChanged(int frameNumber)
  116. \since 4.1
  117. This signal is emitted when the frame number has changed to
  118. \a frameNumber. You can call currentImage() or currentPixmap() to get a
  119. copy of the frame.
  120. */
  121. /*!
  122. \fn void QMovie::stateChanged(QMovie::MovieState state)
  123. This signal is emitted every time the state of the movie changes. The new
  124. state is specified by \a state.
  125. \sa QMovie::state()
  126. */
  127. /*! \fn void QMovie::error(QImageReader::ImageReaderError error)
  128. This signal is emitted by QMovie when the error \a error occurred during
  129. playback. QMovie will stop the movie, and enter QMovie::NotRunning state.
  130. */
  131. /*! \fn void QMovie::finished()
  132. This signal is emitted when the movie has finished.
  133. \sa QMovie::stop()
  134. */
  135. #include "qglobal.h"
  136. #ifndef QT_NO_MOVIE
  137. #include "qmovie.h"
  138. #include "qimage.h"
  139. #include "qimagereader.h"
  140. #include "qpixmap.h"
  141. #include "qrect.h"
  142. #include "qdatetime.h"
  143. #include "qtimer.h"
  144. #include "qpair.h"
  145. #include "qmap.h"
  146. #include "qlist.h"
  147. #include "qbuffer.h"
  148. #include "qdir.h"
  149. #include "private/qobject_p.h"
  150. #define QMOVIE_INVALID_DELAY -1
  151. QT_BEGIN_NAMESPACE
  152. class QFrameInfo
  153. {
  154. public:
  155. QPixmap pixmap;
  156. int delay;
  157. bool endMark;
  158. inline QFrameInfo(bool endMark)
  159. : pixmap(QPixmap()), delay(QMOVIE_INVALID_DELAY), endMark(endMark)
  160. { }
  161. inline QFrameInfo()
  162. : pixmap(QPixmap()), delay(QMOVIE_INVALID_DELAY), endMark(false)
  163. { }
  164. inline QFrameInfo(const QPixmap &pixmap, int delay)
  165. : pixmap(pixmap), delay(delay), endMark(false)
  166. { }
  167. inline bool isValid()
  168. {
  169. return endMark || !(pixmap.isNull() && (delay == QMOVIE_INVALID_DELAY));
  170. }
  171. inline bool isEndMarker()
  172. { return endMark; }
  173. static inline QFrameInfo endMarker()
  174. { return QFrameInfo(true); }
  175. };
  176. class QMoviePrivate : public QObjectPrivate
  177. {
  178. Q_DECLARE_PUBLIC(QMovie)
  179. public:
  180. QMoviePrivate(QMovie *qq);
  181. bool isDone();
  182. bool next();
  183. int speedAdjustedDelay(int delay) const;
  184. bool isValid() const;
  185. bool jumpToFrame(int frameNumber);
  186. int frameCount() const;
  187. bool jumpToNextFrame();
  188. QFrameInfo infoForFrame(int frameNumber);
  189. void reset();
  190. inline void enterState(QMovie::MovieState newState) {
  191. movieState = newState;
  192. emit q_func()->stateChanged(newState);
  193. }
  194. // private slots
  195. void _q_loadNextFrame();
  196. void _q_loadNextFrame(bool starting);
  197. QImageReader *reader;
  198. int speed;
  199. QMovie::MovieState movieState;
  200. QRect frameRect;
  201. QPixmap currentPixmap;
  202. int currentFrameNumber;
  203. int nextFrameNumber;
  204. int greatestFrameNumber;
  205. int nextDelay;
  206. int playCounter;
  207. qint64 initialDevicePos;
  208. QMovie::CacheMode cacheMode;
  209. bool haveReadAll;
  210. bool isFirstIteration;
  211. QMap<int, QFrameInfo> frameMap;
  212. QString absoluteFilePath;
  213. QTimer nextImageTimer;
  214. };
  215. /*! \internal
  216. */
  217. QMoviePrivate::QMoviePrivate(QMovie *qq)
  218. : reader(0), speed(100), movieState(QMovie::NotRunning),
  219. currentFrameNumber(-1), nextFrameNumber(0), greatestFrameNumber(-1),
  220. nextDelay(0), playCounter(-1),
  221. cacheMode(QMovie::CacheNone), haveReadAll(false), isFirstIteration(true)
  222. {
  223. q_ptr = qq;
  224. nextImageTimer.setSingleShot(true);
  225. }
  226. /*! \internal
  227. */
  228. void QMoviePrivate::reset()
  229. {
  230. nextImageTimer.stop();
  231. if (reader->device())
  232. initialDevicePos = reader->device()->pos();
  233. currentFrameNumber = -1;
  234. nextFrameNumber = 0;
  235. greatestFrameNumber = -1;
  236. nextDelay = 0;
  237. playCounter = -1;
  238. haveReadAll = false;
  239. isFirstIteration = true;
  240. frameMap.clear();
  241. }
  242. /*! \internal
  243. */
  244. bool QMoviePrivate::isDone()
  245. {
  246. return (playCounter == 0);
  247. }
  248. /*!
  249. \internal
  250. Given the original \a delay, this function returns the
  251. actual number of milliseconds to delay according to
  252. the current speed. E.g. if the speed is 200%, the
  253. result will be half of the original delay.
  254. */
  255. int QMoviePrivate::speedAdjustedDelay(int delay) const
  256. {
  257. return int( (qint64(delay) * qint64(100) ) / qint64(speed) );
  258. }
  259. /*!
  260. \internal
  261. Returns the QFrameInfo for the given \a frameNumber.
  262. If the frame number is invalid, an invalid QFrameInfo is
  263. returned.
  264. If the end of the animation has been reached, a
  265. special end marker QFrameInfo is returned.
  266. */
  267. QFrameInfo QMoviePrivate::infoForFrame(int frameNumber)
  268. {
  269. if (frameNumber < 0)
  270. return QFrameInfo(); // Invalid
  271. if (haveReadAll && (frameNumber > greatestFrameNumber)) {
  272. if (frameNumber == greatestFrameNumber+1)
  273. return QFrameInfo::endMarker();
  274. return QFrameInfo(); // Invalid
  275. }
  276. if (cacheMode == QMovie::CacheNone) {
  277. if (frameNumber != currentFrameNumber+1) {
  278. // Non-sequential frame access
  279. if (!reader->jumpToImage(frameNumber)) {
  280. if (frameNumber == 0) {
  281. // Special case: Attempt to "rewind" so we can loop
  282. // ### This could be implemented as QImageReader::rewind()
  283. if (reader->device()->isSequential())
  284. return QFrameInfo(); // Invalid
  285. QString fileName = reader->fileName();
  286. QByteArray format = reader->format();
  287. QIODevice *device = reader->device();
  288. QColor bgColor = reader->backgroundColor();
  289. QSize scaledSize = reader->scaledSize();
  290. delete reader;
  291. if (fileName.isEmpty())
  292. reader = new QImageReader(device, format);
  293. else
  294. reader = new QImageReader(absoluteFilePath, format);
  295. (void)reader->canRead(); // Provoke a device->open() call
  296. reader->device()->seek(initialDevicePos);
  297. reader->setBackgroundColor(bgColor);
  298. reader->setScaledSize(scaledSize);
  299. } else {
  300. return QFrameInfo(); // Invalid
  301. }
  302. }
  303. }
  304. if (reader->canRead()) {
  305. // reader says we can read. Attempt to actually read image
  306. QImage anImage = reader->read();
  307. if (anImage.isNull()) {
  308. // Reading image failed.
  309. return QFrameInfo(); // Invalid
  310. }
  311. if (frameNumber > greatestFrameNumber)
  312. greatestFrameNumber = frameNumber;
  313. QPixmap aPixmap = QPixmap::fromImage(anImage);
  314. int aDelay = reader->nextImageDelay();
  315. return QFrameInfo(aPixmap, aDelay);
  316. } else if (frameNumber != 0) {
  317. // We've read all frames now. Return an end marker
  318. haveReadAll = true;
  319. return QFrameInfo::endMarker();
  320. } else {
  321. // No readable frames
  322. haveReadAll = true;
  323. return QFrameInfo();
  324. }
  325. }
  326. // CacheMode == CacheAll
  327. if (frameNumber > greatestFrameNumber) {
  328. // Frame hasn't been read from file yet. Try to do it
  329. for (int i = greatestFrameNumber + 1; i <= frameNumber; ++i) {
  330. if (reader->canRead()) {
  331. // reader says we can read. Attempt to actually read image
  332. QImage anImage = reader->read();
  333. if (anImage.isNull()) {
  334. // Reading image failed.
  335. return QFrameInfo(); // Invalid
  336. }
  337. greatestFrameNumber = i;
  338. QPixmap aPixmap = QPixmap::fromImage(anImage);
  339. int aDelay = reader->nextImageDelay();
  340. QFrameInfo info(aPixmap, aDelay);
  341. // Cache it!
  342. frameMap.insert(i, info);
  343. if (i == frameNumber) {
  344. return info;
  345. }
  346. } else {
  347. // We've read all frames now. Return an end marker
  348. haveReadAll = true;
  349. return QFrameInfo::endMarker();
  350. }
  351. }
  352. }
  353. // Return info for requested (cached) frame
  354. return frameMap.value(frameNumber);
  355. }
  356. /*!
  357. \internal
  358. Attempts to advance the animation to the next frame.
  359. If successful, currentFrameNumber, currentPixmap and
  360. nextDelay are updated accordingly, and true is returned.
  361. Otherwise, false is returned.
  362. When false is returned, isDone() can be called to
  363. determine whether the animation ended gracefully or
  364. an error occurred when reading the frame.
  365. */
  366. bool QMoviePrivate::next()
  367. {
  368. QTime time;
  369. time.start();
  370. QFrameInfo info = infoForFrame(nextFrameNumber);
  371. if (!info.isValid())
  372. return false;
  373. if (info.isEndMarker()) {
  374. // We reached the end of the animation.
  375. if (isFirstIteration) {
  376. if (nextFrameNumber == 0) {
  377. // No frames could be read at all (error).
  378. return false;
  379. }
  380. // End of first iteration. Initialize play counter
  381. playCounter = reader->loopCount();
  382. isFirstIteration = false;
  383. }
  384. // Loop as appropriate
  385. if (playCounter != 0) {
  386. if (playCounter != -1) // Infinite?
  387. playCounter--; // Nope
  388. nextFrameNumber = 0;
  389. return next();
  390. }
  391. // Loop no more. Done
  392. return false;
  393. }
  394. // Image and delay OK, update internal state
  395. currentFrameNumber = nextFrameNumber++;
  396. QSize scaledSize = reader->scaledSize();
  397. if (scaledSize.isValid() && (scaledSize != info.pixmap.size()))
  398. currentPixmap = QPixmap::fromImage( info.pixmap.toImage().scaled(scaledSize) );
  399. else
  400. currentPixmap = info.pixmap;
  401. nextDelay = speedAdjustedDelay(info.delay);
  402. // Adjust delay according to the time it took to read the frame
  403. int processingTime = time.elapsed();
  404. if (processingTime > nextDelay)
  405. nextDelay = 0;
  406. else
  407. nextDelay = nextDelay - processingTime;
  408. return true;
  409. }
  410. /*! \internal
  411. */
  412. void QMoviePrivate::_q_loadNextFrame()
  413. {
  414. _q_loadNextFrame(false);
  415. }
  416. void QMoviePrivate::_q_loadNextFrame(bool starting)
  417. {
  418. Q_Q(QMovie);
  419. if (next()) {
  420. if (starting && movieState == QMovie::NotRunning) {
  421. enterState(QMovie::Running);
  422. emit q->started();
  423. }
  424. if (frameRect.size() != currentPixmap.rect().size()) {
  425. frameRect = currentPixmap.rect();
  426. emit q->resized(frameRect.size());
  427. }
  428. emit q->updated(frameRect);
  429. emit q->frameChanged(currentFrameNumber);
  430. if (movieState == QMovie::Running)
  431. nextImageTimer.start(nextDelay);
  432. } else {
  433. // Could not read another frame
  434. if (!isDone()) {
  435. emit q->error(reader->error());
  436. }
  437. // Graceful finish
  438. if (movieState != QMovie::Paused) {
  439. nextFrameNumber = 0;
  440. isFirstIteration = true;
  441. playCounter = -1;
  442. enterState(QMovie::NotRunning);
  443. emit q->finished();
  444. }
  445. }
  446. }
  447. /*!
  448. \internal
  449. */
  450. bool QMoviePrivate::isValid() const
  451. {
  452. return (greatestFrameNumber >= 0) // have we seen valid data
  453. || reader->canRead(); // or does the reader see valid data
  454. }
  455. /*!
  456. \internal
  457. */
  458. bool QMoviePrivate::jumpToFrame(int frameNumber)
  459. {
  460. if (frameNumber < 0)
  461. return false;
  462. if (currentFrameNumber == frameNumber)
  463. return true;
  464. nextFrameNumber = frameNumber;
  465. if (movieState == QMovie::Running)
  466. nextImageTimer.stop();
  467. _q_loadNextFrame();
  468. return (nextFrameNumber == currentFrameNumber+1);
  469. }
  470. /*!
  471. \internal
  472. */
  473. int QMoviePrivate::frameCount() const
  474. {
  475. int result;
  476. if ((result = reader->imageCount()) != 0)
  477. return result;
  478. if (haveReadAll)
  479. return greatestFrameNumber+1;
  480. return 0; // Don't know
  481. }
  482. /*!
  483. \internal
  484. */
  485. bool QMoviePrivate::jumpToNextFrame()
  486. {
  487. return jumpToFrame(currentFrameNumber+1);
  488. }
  489. /*!
  490. Constructs a QMovie object, passing the \a parent object to QObject's
  491. constructor.
  492. \sa setFileName(), setDevice(), setFormat()
  493. */
  494. QMovie::QMovie(QObject *parent)
  495. : QObject(*new QMoviePrivate(this), parent)
  496. {
  497. Q_D(QMovie);
  498. d->reader = new QImageReader;
  499. connect(&d->nextImageTimer, SIGNAL(timeout()), this, SLOT(_q_loadNextFrame()));
  500. }
  501. /*!
  502. Constructs a QMovie object. QMovie will use read image data from \a
  503. device, which it assumes is open and readable. If \a format is not empty,
  504. QMovie will use the image format \a format for decoding the image
  505. data. Otherwise, QMovie will attempt to guess the format.
  506. The \a parent object is passed to QObject's constructor.
  507. */
  508. QMovie::QMovie(QIODevice *device, const QByteArray &format, QObject *parent)
  509. : QObject(*new QMoviePrivate(this), parent)
  510. {
  511. Q_D(QMovie);
  512. d->reader = new QImageReader(device, format);
  513. d->initialDevicePos = device->pos();
  514. connect(&d->nextImageTimer, SIGNAL(timeout()), this, SLOT(_q_loadNextFrame()));
  515. }
  516. /*!
  517. Constructs a QMovie object. QMovie will use read image data from \a
  518. fileName. If \a format is not empty, QMovie will use the image format \a
  519. format for decoding the image data. Otherwise, QMovie will attempt to
  520. guess the format.
  521. The \a parent object is passed to QObject's constructor.
  522. */
  523. QMovie::QMovie(const QString &fileName, const QByteArray &format, QObject *parent)
  524. : QObject(*new QMoviePrivate(this), parent)
  525. {
  526. Q_D(QMovie);
  527. d->absoluteFilePath = QDir(fileName).absolutePath();
  528. d->reader = new QImageReader(fileName, format);
  529. if (d->reader->device())
  530. d->initialDevicePos = d->reader->device()->pos();
  531. connect(&d->nextImageTimer, SIGNAL(timeout()), this, SLOT(_q_loadNextFrame()));
  532. }
  533. /*!
  534. Destructs the QMovie object.
  535. */
  536. QMovie::~QMovie()
  537. {
  538. Q_D(QMovie);
  539. delete d->reader;
  540. }
  541. /*!
  542. Sets the current device to \a device. QMovie will read image data from
  543. this device when the movie is running.
  544. \sa device(), setFormat()
  545. */
  546. void QMovie::setDevice(QIODevice *device)
  547. {
  548. Q_D(QMovie);
  549. d->reader->setDevice(device);
  550. d->reset();
  551. }
  552. /*!
  553. Returns the device QMovie reads image data from. If no device has
  554. currently been assigned, 0 is returned.
  555. \sa setDevice(), fileName()
  556. */
  557. QIODevice *QMovie::device() const
  558. {
  559. Q_D(const QMovie);
  560. return d->reader->device();
  561. }
  562. /*!
  563. Sets the name of the file that QMovie reads image data from, to \a
  564. fileName.
  565. \sa fileName(), setDevice(), setFormat()
  566. */
  567. void QMovie::setFileName(const QString &fileName)
  568. {
  569. Q_D(QMovie);
  570. d->absoluteFilePath = QDir(fileName).absolutePath();
  571. d->reader->setFileName(fileName);
  572. d->reset();
  573. }
  574. /*!
  575. Returns the name of the file that QMovie reads image data from. If no file
  576. name has been assigned, or if the assigned device is not a file, an empty
  577. QString is returned.
  578. \sa setFileName(), device()
  579. */
  580. QString QMovie::fileName() const
  581. {
  582. Q_D(const QMovie);
  583. return d->reader->fileName();
  584. }
  585. /*!
  586. Sets the format that QMovie will use when decoding image data, to \a
  587. format. By default, QMovie will attempt to guess the format of the image
  588. data.
  589. You can call supportedFormats() for the full list of formats
  590. QMovie supports.
  591. \sa QImageReader::supportedImageFormats()
  592. */
  593. void QMovie::setFormat(const QByteArray &format)
  594. {
  595. Q_D(QMovie);
  596. d->reader->setFormat(format);
  597. }
  598. /*!
  599. Returns the format that QMovie uses when decoding image data. If no format
  600. has been assigned, an empty QByteArray() is returned.
  601. \sa setFormat()
  602. */
  603. QByteArray QMovie::format() const
  604. {
  605. Q_D(const QMovie);
  606. return d->reader->format();
  607. }
  608. /*!
  609. For image formats that support it, this function sets the background color
  610. to \a color.
  611. \sa backgroundColor()
  612. */
  613. void QMovie::setBackgroundColor(const QColor &color)
  614. {
  615. Q_D(QMovie);
  616. d->reader->setBackgroundColor(color);
  617. }
  618. /*!
  619. Returns the background color of the movie. If no background color has been
  620. assigned, an invalid QColor is returned.
  621. \sa setBackgroundColor()
  622. */
  623. QColor QMovie::backgroundColor() const
  624. {
  625. Q_D(const QMovie);
  626. return d->reader->backgroundColor();
  627. }
  628. /*!
  629. Returns the current state of QMovie.
  630. \sa MovieState, stateChanged()
  631. */
  632. QMovie::MovieState QMovie::state() const
  633. {
  634. Q_D(const QMovie);
  635. return d->movieState;
  636. }
  637. /*!
  638. Returns the rect of the last frame. If no frame has yet been updated, an
  639. invalid QRect is returned.
  640. \sa currentImage(), currentPixmap()
  641. */
  642. QRect QMovie::frameRect() const
  643. {
  644. Q_D(const QMovie);
  645. return d->frameRect;
  646. }
  647. /*!
  648. Returns the current frame as a QPixmap.
  649. \sa currentImage(), updated()
  650. */
  651. QPixmap QMovie::currentPixmap() const
  652. {
  653. Q_D(const QMovie);
  654. return d->currentPixmap;
  655. }
  656. /*!
  657. Returns the current frame as a QImage.
  658. \sa currentPixmap(), updated()
  659. */
  660. QImage QMovie::currentImage() const
  661. {
  662. Q_D(const QMovie);
  663. return d->currentPixmap.toImage();
  664. }
  665. /*!
  666. Returns \c true if the movie is valid (e.g., the image data is readable and
  667. the image format is supported); otherwise returns \c false.
  668. */
  669. bool QMovie::isValid() const
  670. {
  671. Q_D(const QMovie);
  672. return d->isValid();
  673. }
  674. /*!
  675. Returns the number of frames in the movie.
  676. Certain animation formats do not support this feature, in which
  677. case 0 is returned.
  678. */
  679. int QMovie::frameCount() const
  680. {
  681. Q_D(const QMovie);
  682. return d->frameCount();
  683. }
  684. /*!
  685. Returns the number of milliseconds QMovie will wait before updating the
  686. next frame in the animation.
  687. */
  688. int QMovie::nextFrameDelay() const
  689. {
  690. Q_D(const QMovie);
  691. return d->nextDelay;
  692. }
  693. /*!
  694. Returns the sequence number of the current frame. The number of the first
  695. frame in the movie is 0.
  696. */
  697. int QMovie::currentFrameNumber() const
  698. {
  699. Q_D(const QMovie);
  700. return d->currentFrameNumber;
  701. }
  702. /*!
  703. Jumps to the next frame. Returns \c true on success; otherwise returns \c false.
  704. */
  705. bool QMovie::jumpToNextFrame()
  706. {
  707. Q_D(QMovie);
  708. return d->jumpToNextFrame();
  709. }
  710. /*!
  711. Jumps to frame number \a frameNumber. Returns \c true on success; otherwise
  712. returns \c false.
  713. */
  714. bool QMovie::jumpToFrame(int frameNumber)
  715. {
  716. Q_D(QMovie);
  717. return d->jumpToFrame(frameNumber);
  718. }
  719. /*!
  720. Returns the number of times the movie will loop before it finishes.
  721. If the movie will only play once (no looping), loopCount returns 0.
  722. If the movie loops forever, loopCount returns -1.
  723. Note that, if the image data comes from a sequential device (e.g. a
  724. socket), QMovie can only loop the movie if the cacheMode is set to
  725. QMovie::CacheAll.
  726. */
  727. int QMovie::loopCount() const
  728. {
  729. Q_D(const QMovie);
  730. return d->reader->loopCount();
  731. }
  732. /*!
  733. If \a paused is true, QMovie will enter \l Paused state and emit
  734. stateChanged(Paused); otherwise it will enter \l Running state and emit
  735. stateChanged(Running).
  736. \sa state()
  737. */
  738. void QMovie::setPaused(bool paused)
  739. {
  740. Q_D(QMovie);
  741. if (paused) {
  742. if (d->movieState == NotRunning)
  743. return;
  744. d->enterState(Paused);
  745. d->nextImageTimer.stop();
  746. } else {
  747. if (d->movieState == Running)
  748. return;
  749. d->enterState(Running);
  750. d->nextImageTimer.start(nextFrameDelay());
  751. }
  752. }
  753. /*!
  754. \property QMovie::speed
  755. \brief the movie's speed
  756. The speed is measured in percentage of the original movie speed.
  757. The default speed is 100%.
  758. Example:
  759. \snippet code/src_gui_image_qmovie.cpp 1
  760. */
  761. void QMovie::setSpeed(int percentSpeed)
  762. {
  763. Q_D(QMovie);
  764. d->speed = percentSpeed;
  765. }
  766. int QMovie::speed() const
  767. {
  768. Q_D(const QMovie);
  769. return d->speed;
  770. }
  771. /*!
  772. Starts the movie. QMovie will enter \l Running state, and start emitting
  773. updated() and resized() as the movie progresses.
  774. If QMovie is in the \l Paused state, this function is equivalent
  775. to calling setPaused(false). If QMovie is already in the \l
  776. Running state, this function does nothing.
  777. \sa stop(), setPaused()
  778. */
  779. void QMovie::start()
  780. {
  781. Q_D(QMovie);
  782. if (d->movieState == NotRunning) {
  783. d->_q_loadNextFrame(true);
  784. } else if (d->movieState == Paused) {
  785. setPaused(false);
  786. }
  787. }
  788. /*!
  789. Stops the movie. QMovie enters \l NotRunning state, and stops emitting
  790. updated() and resized(). If start() is called again, the movie will
  791. restart from the beginning.
  792. If QMovie is already in the \l NotRunning state, this function
  793. does nothing.
  794. \sa start(), setPaused()
  795. */
  796. void QMovie::stop()
  797. {
  798. Q_D(QMovie);
  799. if (d->movieState == NotRunning)
  800. return;
  801. d->enterState(NotRunning);
  802. d->nextImageTimer.stop();
  803. d->nextFrameNumber = 0;
  804. }
  805. /*!
  806. \since 4.1
  807. Returns the scaled size of frames.
  808. \sa QImageReader::scaledSize()
  809. */
  810. QSize QMovie::scaledSize()
  811. {
  812. Q_D(QMovie);
  813. return d->reader->scaledSize();
  814. }
  815. /*!
  816. \since 4.1
  817. Sets the scaled frame size to \a size.
  818. \sa QImageReader::setScaledSize()
  819. */
  820. void QMovie::setScaledSize(const QSize &size)
  821. {
  822. Q_D(QMovie);
  823. d->reader->setScaledSize(size);
  824. }
  825. /*!
  826. \since 4.1
  827. Returns the list of image formats supported by QMovie.
  828. \sa QImageReader::supportedImageFormats()
  829. */
  830. QList<QByteArray> QMovie::supportedFormats()
  831. {
  832. QList<QByteArray> list = QImageReader::supportedImageFormats();
  833. QMutableListIterator<QByteArray> it(list);
  834. QBuffer buffer;
  835. buffer.open(QIODevice::ReadOnly);
  836. while (it.hasNext()) {
  837. QImageReader reader(&buffer, it.next());
  838. if (!reader.supportsAnimation())
  839. it.remove();
  840. }
  841. return list;
  842. }
  843. /*!
  844. \property QMovie::cacheMode
  845. \brief the movie's cache mode
  846. Caching frames can be useful when the underlying animation format handler
  847. that QMovie relies on to decode the animation data does not support
  848. jumping to particular frames in the animation, or even "rewinding" the
  849. animation to the beginning (for looping). Furthermore, if the image data
  850. comes from a sequential device, it is not possible for the underlying
  851. animation handler to seek back to frames whose data has already been read
  852. (making looping altogether impossible).
  853. To aid in such situations, a QMovie object can be instructed to cache the
  854. frames, at the added memory cost of keeping the frames in memory for the
  855. lifetime of the object.
  856. By default, this property is set to \l CacheNone.
  857. \sa QMovie::CacheMode
  858. */
  859. QMovie::CacheMode QMovie::cacheMode() const
  860. {
  861. Q_D(const QMovie);
  862. return d->cacheMode;
  863. }
  864. void QMovie::setCacheMode(CacheMode cacheMode)
  865. {
  866. Q_D(QMovie);
  867. d->cacheMode = cacheMode;
  868. }
  869. QT_END_NAMESPACE
  870. #include "moc_qmovie.cpp"
  871. #endif // QT_NO_MOVIE