Let we make factor for visual that control the speed of image frame animation.
By using speed factor, we can control animated vector image / animated image
frame rendering speed.
For now, we only support the value range as [0.01f 100.0f] for platform safety issue.
(Since it is depend on the thread sleep time. And didn't )
Also we don't implement negative speed factor yet.
Netagive speed factor, and zero speed factor support is TODO.
Change-Id: I53b511d9e9271db1463b54212c95150842981d17
Signed-off-by: Eunki, Hong <eunkiki.hong@samsung.com>
.Add(DevelVisual::Property::CORNER_RADIUS_POLICY, Visual::Transform::Policy::ABSOLUTE)
.Add(DevelVisual::Property::BORDERLINE_WIDTH, 33.3f)
.Add(DevelVisual::Property::BORDERLINE_COLOR, Color::RED)
- .Add(DevelVisual::Property::BORDERLINE_OFFSET, 0.3f));
+ .Add(DevelVisual::Property::BORDERLINE_OFFSET, 0.3f)
+ .Add(DevelImageVisual::Property::FRAME_SPEED_FACTOR, 2.0f));
Property::Map resultMap;
animatedImageVisual.CreatePropertyMap(resultMap);
DALI_TEST_CHECK(value);
DALI_TEST_CHECK(value->Get<int>() == DevelImageVisual::MaskingType::MASKING_ON_RENDERING);
+ value = resultMap.Find(DevelImageVisual::Property::FRAME_SPEED_FACTOR, Property::FLOAT);
+ DALI_TEST_CHECK(value);
+ DALI_TEST_EQUALS(value->Get<float>(), 2.0f, TEST_LOCATION);
+
// Natural size getted as desired size
Vector2 naturalSize;
animatedImageVisual.GetNaturalSize(naturalSize);
.Add("cornerRadiusPolicy", Visual::Transform::Policy::RELATIVE)
.Add("borderlineWidth", 20.0f)
.Add("borderlineColor", Vector4())
- .Add("borderlineOffset", -1.0f));
+ .Add("borderlineOffset", -1.0f)
+ .Add("frameSpeedFactor", 0.5f));
Property::Map resultMap;
animatedImageVisual.CreatePropertyMap(resultMap);
DALI_TEST_CHECK(value);
DALI_TEST_CHECK(value->Get<int>() == DevelImageVisual::MaskingType::MASKING_ON_RENDERING);
+ value = resultMap.Find(DevelImageVisual::Property::FRAME_SPEED_FACTOR, Property::FLOAT);
+ DALI_TEST_CHECK(value);
+ DALI_TEST_EQUALS(value->Get<float>(), 0.5f, TEST_LOCATION);
+
END_TEST;
}
propertyMap.Insert(ImageVisual::Property::BATCH_SIZE, 2);
propertyMap.Insert(ImageVisual::Property::CACHE_SIZE, 4);
propertyMap.Insert(ImageVisual::Property::FRAME_DELAY, 20);
+ propertyMap.Insert(DevelImageVisual::Property::FRAME_SPEED_FACTOR, 1.5f);
VisualFactory factory = VisualFactory::Get();
Visual::Base visual = factory.CreateVisual(propertyMap);
propertyMap.Insert(ImageVisual::Property::BATCH_SIZE, 4);
propertyMap.Insert(ImageVisual::Property::CACHE_SIZE, 8);
propertyMap.Insert(ImageVisual::Property::FRAME_DELAY, 100);
+ propertyMap.Insert(DevelImageVisual::Property::FRAME_SPEED_FACTOR, 1.5f);
VisualFactory factory = VisualFactory::Get();
Visual::Base visual = factory.CreateVisual(propertyMap);
int desiredHeight = 20;
// texture size have to keep it's ratio. So, the size of texture should be 20x20.
- const int resultWidth = 20;
+ const int resultWidth = 20;
const int resultHeight = 20;
Visual::Base visual = VisualFactory::Get().CreateVisual(TEST_GIF_FILE_NAME, ImageDimensions(desiredWidth, desiredHeight));
.Add(ImageVisual::Property::URL, TEST_VECTOR_IMAGE_FILE_NAME)
.Add(DevelImageVisual::Property::LOOP_COUNT, 3)
.Add(DevelImageVisual::Property::PLAY_RANGE, playRange)
+ .Add(DevelImageVisual::Property::FRAME_SPEED_FACTOR, 2.0f)
.Add(DevelVisual::Property::CORNER_RADIUS, 50.0f)
.Add(DevelVisual::Property::BORDERLINE_WIDTH, 20.0f)
.Add(ImageVisual::Property::SYNCHRONOUS_LOADING, false);
.Add("redrawInScalingDown", false)
.Add("enableFrameCache", false)
.Add("notifyAfterRasterization", false)
+ .Add("frameSpeedFactor", 0.5f)
.Add("cornerRadius", cornerRadius)
.Add("borderlineWidth", borderlineWidth)
.Add("borderlineColor", borderlineColor)
DALI_TEST_CHECK(value);
DALI_TEST_CHECK(value->Get<bool>() == false);
+ value = resultMap.Find(DevelImageVisual::Property::FRAME_SPEED_FACTOR, Property::FLOAT);
+ DALI_TEST_CHECK(value);
+ DALI_TEST_CHECK(value->Get<float>() == 0.5f);
+
value = resultMap.Find(DevelVisual::Property::CORNER_RADIUS, Property::VECTOR4);
DALI_TEST_CHECK(value);
DALI_TEST_EQUALS(value->Get<Vector4>(), Vector4(cornerRadius, cornerRadius, cornerRadius, cornerRadius), TEST_LOCATION);
END_TEST;
}
+int UtcDaliAnimatedVectorImageVisualFrameSpeedFactor(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline("UtcDaliAnimatedVectorImageVisualFrameSpeedFactor");
+
+ Property::Map propertyMap;
+ propertyMap.Add(Toolkit::Visual::Property::TYPE, DevelVisual::ANIMATED_VECTOR_IMAGE)
+ .Add(ImageVisual::Property::URL, TEST_VECTOR_IMAGE_FILE_NAME)
+ .Add(ImageVisual::Property::SYNCHRONOUS_LOADING, false);
+
+ Visual::Base visual = VisualFactory::Get().CreateVisual(propertyMap);
+ DALI_TEST_CHECK(visual);
+
+ DummyControl actor = DummyControl::New(true);
+ DummyControlImpl& dummyImpl = static_cast<DummyControlImpl&>(actor.GetImplementation());
+ dummyImpl.RegisterVisual(DummyControl::Property::TEST_VISUAL, visual);
+
+ Vector2 controlSize(20.f, 30.f);
+ actor.SetProperty(Actor::Property::SIZE, controlSize);
+
+ application.GetScene().Add(actor);
+
+ application.SendNotification();
+ application.Render();
+
+ // Trigger count is 2 - load & render a frame
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(2), true, TEST_LOCATION);
+
+ Property::Map map = actor.GetProperty<Property::Map>(DummyControl::Property::TEST_VISUAL);
+ Property::Value* value = map.Find(DevelImageVisual::Property::FRAME_SPEED_FACTOR);
+ DALI_TEST_EQUALS(value->Get<float>(), 1.0f, TEST_LOCATION); // Check default value is 1.0f
+
+ Property::Map attributes;
+ attributes.Add(DevelImageVisual::Property::FRAME_SPEED_FACTOR, 0.5f);
+
+ DevelControl::DoAction(actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes);
+
+ application.SendNotification();
+ application.Render();
+
+ map = actor.GetProperty<Property::Map>(DummyControl::Property::TEST_VISUAL);
+ value = map.Find(DevelImageVisual::Property::FRAME_SPEED_FACTOR);
+ DALI_TEST_EQUALS(value->Get<float>(), 0.5f, TEST_LOCATION);
+
+ attributes.Clear();
+ attributes.Add(DevelImageVisual::Property::FRAME_SPEED_FACTOR, 8.0f);
+
+ DevelControl::DoAction(actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes);
+
+ application.SendNotification();
+ application.Render();
+
+ map = actor.GetProperty<Property::Map>(DummyControl::Property::TEST_VISUAL);
+ value = map.Find(DevelImageVisual::Property::FRAME_SPEED_FACTOR);
+ DALI_TEST_EQUALS(value->Get<float>(), 8.0f, TEST_LOCATION);
+
+ // TODO : Below logic might be changed in future.
+
+ // Clampled by maximum frame speed factor.
+ attributes.Clear();
+ attributes.Add(DevelImageVisual::Property::FRAME_SPEED_FACTOR, 100.0f + 1.0f);
+
+ DevelControl::DoAction(actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes);
+
+ application.SendNotification();
+ application.Render();
+
+ map = actor.GetProperty<Property::Map>(DummyControl::Property::TEST_VISUAL);
+ value = map.Find(DevelImageVisual::Property::FRAME_SPEED_FACTOR);
+ DALI_TEST_EQUALS(value->Get<float>(), 100.0f, TEST_LOCATION);
+
+ // Clampled by minimum frame speed factor.
+ attributes.Clear();
+ attributes.Add(DevelImageVisual::Property::FRAME_SPEED_FACTOR, 0.0f);
+
+ DevelControl::DoAction(actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes);
+
+ application.SendNotification();
+ application.Render();
+
+ map = actor.GetProperty<Property::Map>(DummyControl::Property::TEST_VISUAL);
+ value = map.Find(DevelImageVisual::Property::FRAME_SPEED_FACTOR);
+ DALI_TEST_EQUALS(value->Get<float>(), 0.01f, TEST_LOCATION);
+
+ // Clampled by minimum frame speed factor 2.
+ attributes.Clear();
+ attributes.Add(DevelImageVisual::Property::FRAME_SPEED_FACTOR, -1.0f);
+
+ DevelControl::DoAction(actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes);
+
+ application.SendNotification();
+ application.Render();
+
+ map = actor.GetProperty<Property::Map>(DummyControl::Property::TEST_VISUAL);
+ value = map.Find(DevelImageVisual::Property::FRAME_SPEED_FACTOR);
+ DALI_TEST_EQUALS(value->Get<float>(), 0.01f, TEST_LOCATION);
+
+ // Clampled by minimum frame speed factor 3.
+ attributes.Clear();
+ attributes.Add(DevelImageVisual::Property::FRAME_SPEED_FACTOR, -100.0f - 1.0f);
+
+ DevelControl::DoAction(actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes);
+
+ application.SendNotification();
+ application.Render();
+
+ map = actor.GetProperty<Property::Map>(DummyControl::Property::TEST_VISUAL);
+ value = map.Find(DevelImageVisual::Property::FRAME_SPEED_FACTOR);
+ DALI_TEST_EQUALS(value->Get<float>(), 0.01f, TEST_LOCATION);
+
+ END_TEST;
+}
+
int UtcDaliAnimatedVectorImageVisualPropertyNotification(void)
{
ToolkitTestApplication application;
* If this property is true, ImageVisual ignores mDesiredSize.
* @note Used by the ImageVisual. The default is false.
*/
- SYNCHRONOUS_SIZING = ORIENTATION_CORRECTION + 18
+ SYNCHRONOUS_SIZING = ORIENTATION_CORRECTION + 18,
+
+ /**
+ * @brief Specifies a speed factor for the animated image frame.
+ * @details Name "frameSpeedFactor", type Property::FLOAT.
+ *
+ * The speed factor is a multiplier of the normal velocity of the animation. Values between [0,1] will
+ * slow down the animation and values above one will speed up the animation.
+ *
+ * @note The range of this value is clamped between [0.01f ~ 100.0f].
+ * It might be supported out of bound, and negative value in future.
+ * @note It is used in the AnimatedImageVisual and AnimatedVectorImageVisual. The default is 1.0f.
+ */
+ FRAME_SPEED_FACTOR = ORIENTATION_CORRECTION + 19,
};
} //namespace Property
static constexpr auto LOOP_FOREVER = -1;
static constexpr auto FIRST_LOOP = 0u;
+constexpr float MINIMUM_FRAME_SPEED_FACTOR(0.01f);
+constexpr float MAXIMUM_FRAME_SPEED_FACTOR(100.0f);
+
constexpr uint32_t TEXTURE_COUNT_FOR_GPU_ALPHA_MASK = 2u;
#if defined(DEBUG_ENABLED)
Debug::Filter* gAnimImgLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_ANIMATED_IMAGE");
#endif
+
+/**
+ * @brief Safety method to calculate interval with speed factor.
+ */
+template<typename T>
+inline uint32_t CalculateInterval(const T interval, const float frameSpeedFactor)
+{
+ return DALI_LIKELY(Dali::Equals(frameSpeedFactor, 1.0f)) ? static_cast<uint32_t>(interval) : static_cast<uint32_t>(static_cast<float>(interval) / (frameSpeedFactor));
+}
} // namespace
/**
mReleasePolicy(Toolkit::ImageVisual::ReleasePolicy::DETACHED),
mMaskingData(),
mDesiredSize(desiredSize),
+ mFrameSpeedFactor(1.0f),
mFrameCount(0),
mImageSize(),
mActionStatus(DevelAnimatedImageVisual::Action::PLAY),
map.Insert(Toolkit::ImageVisual::Property::SAMPLING_MODE, mSamplingMode);
map.Insert(Toolkit::ImageVisual::Property::DESIRED_WIDTH, mDesiredSize.GetWidth());
map.Insert(Toolkit::ImageVisual::Property::DESIRED_HEIGHT, mDesiredSize.GetHeight());
+ map.Insert(Toolkit::DevelImageVisual::Property::FRAME_SPEED_FACTOR, mFrameSpeedFactor);
}
void AnimatedImageVisual::DoCreateInstancePropertyMap(Property::Map& map) const
{
DoSetProperty(Toolkit::ImageVisual::Property::DESIRED_HEIGHT, keyValue.second);
}
+ else if(keyValue.first == FRAME_SPEED_FACTOR)
+ {
+ DoSetProperty(Toolkit::DevelImageVisual::Property::FRAME_SPEED_FACTOR, keyValue.second);
+ }
}
}
// Load image immediately if LOAD_POLICY requires it
mFrameDelay = frameDelay;
if(DALI_LIKELY(mImageCache))
{
- mImageCache->SetInterval(static_cast<uint32_t>(mFrameDelay));
+ mImageCache->SetInterval(CalculateInterval(mFrameDelay, mFrameSpeedFactor));
}
}
break;
}
break;
}
+
+ case Toolkit::DevelImageVisual::Property::FRAME_SPEED_FACTOR:
+ {
+ float frameSpeedFactor = 1.0f;
+ if(value.Get(frameSpeedFactor))
+ {
+ // TODO : Could we remove this limitation?
+ Dali::ClampInPlace(frameSpeedFactor, MINIMUM_FRAME_SPEED_FACTOR, MAXIMUM_FRAME_SPEED_FACTOR);
+
+ if(!Dali::Equals(mFrameSpeedFactor, frameSpeedFactor))
+ {
+ mFrameSpeedFactor = frameSpeedFactor;
+ }
+ }
+ break;
+ }
}
}
{
if(mFrameCount > SINGLE_IMAGE_COUNT)
{
- mFrameDelayTimer = Timer::New(firstInterval);
+ mFrameDelayTimer = Timer::New(CalculateInterval(firstInterval, mFrameSpeedFactor));
mFrameDelayTimer.TickSignal().Connect(this, &AnimatedImageVisual::DisplayNextFrame);
mFrameDelayTimer.Start();
}
{
if(mFrameDelayTimer && interval > 0u)
{
- mFrameDelayTimer.SetInterval(interval);
+ mFrameDelayTimer.SetInterval(CalculateInterval(interval, mFrameSpeedFactor));
}
mImpl->mRenderer.SetTextures(textureSet);
CheckMaskTexture();
mImpl->mRenderer.SetTextures(textureSet);
CheckMaskTexture();
}
- mFrameDelayTimer.SetInterval(mImageCache->GetFrameInterval(frameIndex));
+ mFrameDelayTimer.SetInterval(CalculateInterval(mImageCache->GetFrameInterval(frameIndex), mFrameSpeedFactor));
}
mCurrentFrameIndex = frameIndex;
#define DALI_TOOLKIT_INTERNAL_ANIMATED_IMAGE_VISUAL_H
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
// EXTERNAL INCLUDES
#include <dali/devel-api/actors/actor-devel.h>
-#include <dali/public-api/adaptor-framework/window.h>
#include <dali/devel-api/adaptor-framework/animated-image-loading.h>
#include <dali/public-api/adaptor-framework/timer.h>
+#include <dali/public-api/adaptor-framework/window.h>
#include <dali/public-api/common/dali-vector.h>
#include <dali/public-api/common/intrusive-ptr.h>
#include <dali/public-api/math/vector4.h>
Dali::Toolkit::ImageVisual::ReleasePolicy::Type mReleasePolicy;
TextureManager::MaskingDataPointer mMaskingData;
Dali::ImageDimensions mDesiredSize;
+ float mFrameSpeedFactor;
// Shared variables
uint32_t mFrameCount; // Number of frames
DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::Toolkit::DevelImageVisual::LoopingMode, AUTO_REVERSE)
DALI_ENUM_TO_STRING_TABLE_END(LOOPING_MODE)
+constexpr float MINIMUM_FRAME_SPEED_FACTOR(0.01f);
+constexpr float MAXIMUM_FRAME_SPEED_FACTOR(100.0f);
+
#if defined(DEBUG_ENABLED)
Debug::Filter* gVectorAnimationLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_VECTOR_ANIMATION");
#endif
mPlacementActor(),
mPlayState(DevelImageVisual::PlayState::STOPPED),
mEventCallback(nullptr),
+ mFrameSpeedFactor(1.0f),
mLastSentPlayStateId(0u),
mLoadFailed(false),
mRendererAdded(false),
map.Insert(Toolkit::ImageVisual::Property::DESIRED_HEIGHT, mDesiredSize.GetHeight());
map.Insert(Toolkit::DevelImageVisual::Property::ENABLE_FRAME_CACHE, mEnableFrameCache);
map.Insert(Toolkit::DevelImageVisual::Property::NOTIFY_AFTER_RASTERIZATION, mNotifyAfterRasterization);
+ map.Insert(Toolkit::DevelImageVisual::Property::FRAME_SPEED_FACTOR, mFrameSpeedFactor);
}
void AnimatedVectorImageVisual::DoCreateInstancePropertyMap(Property::Map& map) const
{
DoSetProperty(Toolkit::DevelImageVisual::Property::NOTIFY_AFTER_RASTERIZATION, keyValue.second);
}
+ else if(keyValue.first == FRAME_SPEED_FACTOR)
+ {
+ DoSetProperty(Toolkit::DevelImageVisual::Property::FRAME_SPEED_FACTOR, keyValue.second);
+ }
}
}
}
break;
}
+
+ case Toolkit::DevelImageVisual::Property::FRAME_SPEED_FACTOR:
+ {
+ float frameSpeedFactor = 1.0f;
+ if(value.Get(frameSpeedFactor))
+ {
+ // TODO : Could we remove this limitation?
+ Dali::ClampInPlace(frameSpeedFactor, MINIMUM_FRAME_SPEED_FACTOR, MAXIMUM_FRAME_SPEED_FACTOR);
+
+ if(!Dali::Equals(mFrameSpeedFactor, frameSpeedFactor))
+ {
+ mFrameSpeedFactor = frameSpeedFactor;
+
+ mAnimationData.frameSpeedFactor = mFrameSpeedFactor;
+ mAnimationData.resendFlag |= VectorAnimationTask::RESEND_FRAME_SPEED_FACTOR;
+ }
+ }
+ break;
+ }
}
}
WeakHandle<Actor> mPlacementActor;
DevelImageVisual::PlayState::Type mPlayState;
CallbackBase* mEventCallback; // Not owned
+ float mFrameSpeedFactor;
uint32_t mLastSentPlayStateId;
}
#endif
+int64_t CalculateFrameDurationMicroSeconds(const float frameRate, const float frameSpeedFactor)
+{
+ return static_cast<int64_t>(MICROSECONDS_PER_SECOND / static_cast<double>(frameRate * frameSpeedFactor));
+}
+
} // unnamed namespace
VectorAnimationTask::VectorAnimationTask(VisualFactoryCache& factoryCache)
mNextFrameStartTime(),
mFrameDurationMicroSeconds(MICROSECONDS_PER_SECOND / 60.0f),
mFrameRate(60.0f),
+ mFrameSpeedFactor(1.0f),
mCurrentFrame(0),
mTotalFrame(0),
mStartFrame(0),
mEndFrame = mTotalFrame - 1;
- mFrameRate = mVectorRenderer.GetFrameRate();
- mFrameDurationMicroSeconds = MICROSECONDS_PER_SECOND / mFrameRate;
+ mFrameRate = mVectorRenderer.GetFrameRate();
+
+ mFrameDurationMicroSeconds = CalculateFrameDurationMicroSeconds(mFrameRate, mFrameSpeedFactor);
mLoadRequest = false;
{
return frame;
}
+/// Event & VectorAnimationThread called after Rasterize() finished.
VectorAnimationTask::TimePoint VectorAnimationTask::CalculateNextFrameTime(bool renderNow)
{
// std::chrono::time_point template has second parameter duration which defaults to the std::chrono::steady_clock supported
// duration. In some C++11 implementations it is a milliseconds duration, so it fails to compile unless mNextFrameStartTime
// is casted to use the default duration.
- mNextFrameStartTime = std::chrono::time_point_cast<TimePoint::duration>(mNextFrameStartTime + std::chrono::microseconds(mFrameDurationMicroSeconds));
- auto current = std::chrono::steady_clock::now();
- mDroppedFrames = 0;
+ auto current = std::chrono::steady_clock::now();
if(renderNow)
{
mNextFrameStartTime = current;
+ mDroppedFrames = 0;
}
- else if(mNextFrameStartTime < current)
+ else
{
- uint32_t droppedFrames = 0;
+ const auto durationMicroSeconds = std::chrono::microseconds(mFrameDurationMicroSeconds);
- while(current > std::chrono::time_point_cast<TimePoint::duration>(mNextFrameStartTime + std::chrono::microseconds(mFrameDurationMicroSeconds)) && droppedFrames < mTotalFrame)
+ mNextFrameStartTime = std::chrono::time_point_cast<TimePoint::duration>(mNextFrameStartTime + durationMicroSeconds);
+ if(mNextFrameStartTime < current)
{
- droppedFrames++;
- mNextFrameStartTime = std::chrono::time_point_cast<TimePoint::duration>(mNextFrameStartTime + std::chrono::microseconds(mFrameDurationMicroSeconds));
- }
+ uint32_t droppedFrames = 0;
- mNextFrameStartTime = current;
- mDroppedFrames = droppedFrames;
+ while(current > std::chrono::time_point_cast<TimePoint::duration>(mNextFrameStartTime + durationMicroSeconds) && droppedFrames < mTotalFrame)
+ {
+ droppedFrames++;
+ mNextFrameStartTime = std::chrono::time_point_cast<TimePoint::duration>(mNextFrameStartTime + durationMicroSeconds);
+ }
+
+ mNextFrameStartTime = current;
+ mDroppedFrames = droppedFrames;
+ }
}
return mNextFrameStartTime;
mNotifyAfterRasterization = animationData.notifyAfterRasterization;
}
+ if(animationData.resendFlag & VectorAnimationTask::RESEND_FRAME_SPEED_FACTOR)
+ {
+ mFrameSpeedFactor = animationData.frameSpeedFactor;
+
+ // Recalculate frame duration with new frame speed factor.
+ mFrameDurationMicroSeconds = CalculateFrameDurationMicroSeconds(mFrameRate, mFrameSpeedFactor);
+ }
+
if(animationData.resendFlag & VectorAnimationTask::RESEND_NEED_RESOURCE_READY)
{
mVectorRenderer.InvalidateBuffer();
RESEND_NEED_RESOURCE_READY = 1 << 7,
RESEND_DYNAMIC_PROPERTY = 1 << 8,
RESEND_NOTIFY_AFTER_RASTERIZATION = 1 << 9,
+ RESEND_FRAME_SPEED_FACTOR = 1 << 10,
};
/**
height(0),
loopCount(-1),
playStateId(0),
+ frameSpeedFactor(1.0f),
notifyAfterRasterization(false)
{
}
height = rhs.height;
loopCount = rhs.loopCount;
playStateId = rhs.playStateId;
+ frameSpeedFactor = rhs.frameSpeedFactor;
notifyAfterRasterization = rhs.notifyAfterRasterization;
+
dynamicProperties.insert(dynamicProperties.end(), rhs.dynamicProperties.begin(), rhs.dynamicProperties.end());
return *this;
}
uint32_t height;
int32_t loopCount;
uint32_t playStateId;
+ float frameSpeedFactor;
bool notifyAfterRasterization;
};
TimePoint mNextFrameStartTime;
int64_t mFrameDurationMicroSeconds;
float mFrameRate;
+ float mFrameSpeedFactor;
uint32_t mCurrentFrame;
uint32_t mTotalFrame;
uint32_t mStartFrame;
const char* const ENABLE_FRAME_CACHE("enableFrameCache");
const char* const NOTIFY_AFTER_RASTERIZATION("notifyAfterRasterization");
const char* const SYNCHRONOUS_SIZING("synchronousSizing");
+const char* const FRAME_SPEED_FACTOR("frameSpeedFactor");
// Text visual
const char* const TEXT_PROPERTY("text");
extern const char* const ENABLE_FRAME_CACHE;
extern const char* const NOTIFY_AFTER_RASTERIZATION;
extern const char* const SYNCHRONOUS_SIZING;
+extern const char* const FRAME_SPEED_FACTOR;
// Text visual
extern const char* const TEXT_PROPERTY;