Revision control
++ // 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
++ // Qt-Security score:significant reason:default
++
++ #include "qquicksprite_p.h"
++ #include "qquickimagebase_p.h"
++ #include <qqml.h>
++ #include <QQmlContext>
++ #include <QDebug>
++ #include <QRandomGenerator>
++
++ QT_BEGIN_NAMESPACE
++
++ /*!
++ \qmltype Sprite
++ \nativetype QQuickSprite
++ \inqmlmodule QtQuick
++ \ingroup qtquick-visual-utility
++ \brief Specifies sprite animations.
++
++ Sprite defines a series of one or more frames to be animated and rendered by SpriteSequence.
++ The sprites can be in the middle of an image file, or split along multiple rows, as long as they form
++ a contiguous line wrapping to the next row of the file from the left edge of the file.
++
++ For full details, see the \l{Sprite Animations} overview.
++ */
++ /*!
++ \qmlproperty int QtQuick::Sprite::duration
++
++ Duration of the animation. Values below 0 are invalid.
++
++ If frameRate is valid then it will be used to calculate the duration of the frames.
++ If not, and frameDuration is valid, then frameDuration will be used. Otherwise duration is used.
++ */
++ /*!
++ \qmlproperty int QtQuick::Sprite::durationVariation
++
++ The duration of the animation can vary by up to this amount. Variation will never decrease the
++ length of the animation to less than 0.
++
++ durationVariation will only take effect if duration is
++ used to calculate the duration of frames.
++
++ Default is 0.
++ */
++
++ /*!
++ \qmlproperty real QtQuick::Sprite::frameRate
++
++ Frames per second to show in the animation. Values below 0 are invalid.
++
++ If frameRate is valid then it will be used to calculate the duration of the frames.
++ If not, and frameDuration is valid , then frameDuration will be used. Otherwise duration is used.
++ */
++ /*!
++ \qmlproperty real QtQuick::Sprite::frameRateVariation
++
++ The frame rate between animations can vary by up to this amount. Variation will never decrease the
++ length of the animation to less than 0.
++
++ frameRateVariation will only take effect if frameRate is
++ used to calculate the duration of frames.
++
++ Default is 0.
++ */
++
++ /*!
++ \qmlproperty int QtQuick::Sprite::frameDuration
++
++ Duration of each frame of the animation in milliseconds. Values below 0 are invalid.
++
++ If frameRate is valid then it will be used to calculate the duration of the frames.
++ If not, and frameDuration is valid, then frameDuration will be used. Otherwise duration is used.
++ */
++ /*!
++ \qmlproperty int QtQuick::Sprite::frameDurationVariation
++
++ The duration of a frame in the animation can vary by up to this amount. Variation will never decrease the
++ length of the animation to less than 0.
++
++ frameDurationVariation will only take effect if frameDuration is
++ used to calculate the duration of frames.
++
++ Default is 0.
++ */
++
++ /*!
++ \qmlproperty string QtQuick::Sprite::name
++
++ The name of this sprite, for use in the to property of other sprites.
++ */
++ /*!
++ \qmlproperty QVariantMap QtQuick::Sprite::to
++
++ A list of other sprites and weighted transitions to them,
++ for example {"a":1, "b":2, "c":0} would specify that one-third should
++ transition to sprite "a" when this sprite is done, and two-thirds should
++ transition to sprite "b" when this sprite is done. As the transitions are
++ chosen randomly, these proportions will not be exact. With "c":0 in the list,
++ no sprites will randomly transition to "c", but it wll be a valid path if a sprite
++ goal is set.
++
++ If no list is specified, or the sum of weights in the list is zero, then the sprite
++ will repeat itself after completing.
++ */
++ /*!
++ \qmlproperty int QtQuick::Sprite::frameCount
++
++ Number of frames in this sprite.
++ */
++ /*!
++ \qmlproperty int QtQuick::Sprite::frameHeight
++
++ Height of a single frame in this sprite.
++ */
++ /*!
++ \qmlproperty int QtQuick::Sprite::frameWidth
++
++ Width of a single frame in this sprite.
++ */
++ /*!
++ \qmlproperty int QtQuick::Sprite::frameX
++
++ The X coordinate in the image file of the first frame of the sprite.
++ */
++ /*!
++ \qmlproperty int QtQuick::Sprite::frameY
++
++ The Y coordinate in the image file of the first frame of the sprite.
++ */
++ /*!
++ \qmlproperty url QtQuick::Sprite::source
++
++ The image source for the animation.
++
++ If frameHeight and frameWidth are not specified, it is assumed to be a single long row of square frames.
++ Otherwise, it can be multiple contiguous rows or rectangluar frames, when one row runs out the next will be used.
++
++ If frameX and frameY are specified, the row of frames will be taken with that x/y coordinate as the upper left corner.
++ */
++
++ /*!
++ \qmlproperty bool QtQuick::Sprite::reverse
++
++ If true, then the animation will be played in reverse.
++
++ Default is false.
++ */
++
++ /*!
++ \qmlproperty bool QtQuick::Sprite::randomStart
++
++ If true, then the animation will start its first animation with a random amount of its duration skipped.
++ This allows them to not look like they all just started when the animation begins.
++
++ This only affects the very first animation played. Transitioning to another animation, or the same
++ animation again, will not trigger this.
++
++ Default is false.
++ */
++
++ /*!
++ \qmlproperty bool QtQuick::Sprite::frameSync
++
++ If true, then the animation will have no duration. Instead, the animation will advance
++ one frame each time a frame is rendered to the screen. This synchronizes it with the painting
++ rate as opposed to elapsed time.
++
++ If frameSync is set to true, it overrides all of duration, frameRate and frameDuration.
++
++ Default is false.
++ */
++
++ static const int unsetDuration = -2;//-1 means perframe for duration
++ QQuickSprite::QQuickSprite(QObject *parent)
++ : QQuickStochasticState(parent)
++ , m_generatedCount(0)
++ , m_framesPerRow(0)
++ , m_rowY(0)
++ , m_rowStartX(0)
++ , m_reverse(false)
++ , m_frameHeight(0)
++ , m_frameWidth(0)
++ , m_frames(1)
++ , m_frameX(0)
++ , m_frameY(0)
++ , m_frameRate(unsetDuration)
++ , m_frameRateVariation(0)
++ , m_frameDuration(unsetDuration)
++ , m_frameDurationVariation(0)
++ , m_frameSync(false)
++ , m_devicePixelRatio(1.0)
++ {
++ }
++
++ /*! \internal */
++ QQuickSprite::~QQuickSprite()
++ {
++ }
++
++ int QQuickSprite::variedDuration() const //Deals with precedence when multiple durations are set
++ {
++ if (m_frameSync)
++ return 0;
++
++ if (m_frameRate != unsetDuration) {
++ qreal fpms = (m_frameRate
++ + (m_frameRateVariation * QRandomGenerator::global()->generateDouble() * 2)
++ - m_frameRateVariation) / 1000.0;
++ return qMax(qreal(0.0) , m_frames / fpms);
++ } else if (m_frameDuration != unsetDuration) {
++ int mspf = m_frameDuration
++ + (m_frameDurationVariation * QRandomGenerator::global()->generateDouble() * 2)
++ - m_frameDurationVariation;
++ return qMax(0, m_frames * mspf);
++ } else if (duration() >= 0) {
++ qWarning() << "Sprite::duration is changing meaning to the full animation duration.";
++ qWarning() << "Use Sprite::frameDuration for the old meaning, of per frame duration.";
++ qWarning() << "As an interim measure, duration/durationVariation means the same as frameDuration/frameDurationVariation, and you'll get this warning spewed out everywhere to motivate you.";
++ //Note that the spammyness is due to this being the best location to detect, but also called once each animation loop
++ return QQuickStochasticState::variedDuration() * m_frames;
++ }
++ return 1000; //When nothing set
++ }
++
++ void QQuickSprite::startImageLoading()
++ {
++ m_pix.clear(this);
++ if (!m_source.isEmpty()) {
++ const QQmlContext *context = qmlContext(this);
++ QQmlEngine *e = context ? context->engine() : nullptr;
++ if (!e) { //If not created in QML, you must set the QObject parent to the QML element so this can work
++ context = qmlContext(parent());
++ e = context ? context->engine() : nullptr;
++ if (!e)
++ qWarning() << "QQuickSprite: Cannot find QQmlEngine - this class is only for use in QML and may not work";
++ }
++ const QUrl resolvedUrl = context ? context->resolvedUrl(m_source) : m_source;
++ QUrl loadUrl = resolvedUrl;
++ QQuickImageBase::resolve2xLocalFile(resolvedUrl, m_devicePixelRatio, &loadUrl,
++ &m_devicePixelRatio);
++
++ m_pix.load(e, loadUrl);
++ }
++ }
++
++ QT_END_NAMESPACE
++
++ #include "moc_qquicksprite_p.cpp"