blob: 93b9decd9cbc3c80be2cd422ebecf84364daea8f [file] [log] [blame]
John Recke45b1fd2014-04-15 09:50:16 -07001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
John Recke45b1fd2014-04-15 09:50:16 -070017#include "Animator.h"
18
John Reck68bfe0a2014-06-24 15:34:58 -070019#include <inttypes.h>
John Recke45b1fd2014-04-15 09:50:16 -070020#include <set>
21
John Reck119907c2014-08-14 09:02:01 -070022#include "AnimationContext.h"
Tom Hudson2dc236b2014-10-15 15:46:42 -040023#include "Interpolator.h"
John Reck52244ff2014-05-01 21:27:37 -070024#include "RenderNode.h"
John Recke45b1fd2014-04-15 09:50:16 -070025#include "RenderProperties.h"
26
27namespace android {
28namespace uirenderer {
29
30/************************************************************
John Reckff941dc2014-05-14 16:34:14 -070031 * BaseRenderNodeAnimator
John Recke45b1fd2014-04-15 09:50:16 -070032 ************************************************************/
33
John Reckff941dc2014-05-14 16:34:14 -070034BaseRenderNodeAnimator::BaseRenderNodeAnimator(float finalValue)
Chris Craikd41c4d82015-01-05 15:51:13 -080035 : mTarget(nullptr)
Doris Liu8b083202016-02-19 21:46:06 +000036 , mStagingTarget(nullptr)
John Reck8d8af3c2014-07-01 15:23:45 -070037 , mFinalValue(finalValue)
John Reckff941dc2014-05-14 16:34:14 -070038 , mDeltaValue(0)
39 , mFromValue(0)
Chris Craikb9ce116d2015-08-20 15:14:06 -070040 , mStagingPlayState(PlayState::NotStarted)
41 , mPlayState(PlayState::NotStarted)
John Reck68bfe0a2014-06-24 15:34:58 -070042 , mHasStartValue(false)
John Recke45b1fd2014-04-15 09:50:16 -070043 , mStartTime(0)
Alan Viverettead2f8e32014-05-16 13:28:33 -070044 , mDuration(300)
Chris Craik572d9ac2014-09-12 17:40:20 -070045 , mStartDelay(0)
Doris Liuc4bb1852016-02-19 21:39:21 +000046 , mMayRunAsync(true)
John Reck1bcacfd2017-11-03 10:12:19 -070047 , mPlayTime(0) {}
John Recke45b1fd2014-04-15 09:50:16 -070048
John Reck1bcacfd2017-11-03 10:12:19 -070049BaseRenderNodeAnimator::~BaseRenderNodeAnimator() {}
John Reck68bfe0a2014-06-24 15:34:58 -070050
51void BaseRenderNodeAnimator::checkMutable() {
52 // Should be impossible to hit as the Java-side also has guards for this
Chris Craikb9ce116d2015-08-20 15:14:06 -070053 LOG_ALWAYS_FATAL_IF(mStagingPlayState != PlayState::NotStarted,
John Reck1bcacfd2017-11-03 10:12:19 -070054 "Animator has already been started!");
John Recke45b1fd2014-04-15 09:50:16 -070055}
56
John Reckff941dc2014-05-14 16:34:14 -070057void BaseRenderNodeAnimator::setInterpolator(Interpolator* interpolator) {
John Reck68bfe0a2014-06-24 15:34:58 -070058 checkMutable();
Chris Craik51d6a3d2014-12-22 17:16:56 -080059 mInterpolator.reset(interpolator);
John Recke45b1fd2014-04-15 09:50:16 -070060}
61
John Reckff941dc2014-05-14 16:34:14 -070062void BaseRenderNodeAnimator::setStartValue(float value) {
John Reck68bfe0a2014-06-24 15:34:58 -070063 checkMutable();
64 doSetStartValue(value);
John Reckff941dc2014-05-14 16:34:14 -070065}
66
John Reck68bfe0a2014-06-24 15:34:58 -070067void BaseRenderNodeAnimator::doSetStartValue(float value) {
68 mFromValue = value;
69 mDeltaValue = (mFinalValue - mFromValue);
70 mHasStartValue = true;
John Reckff941dc2014-05-14 16:34:14 -070071}
72
Alan Viverettead2f8e32014-05-16 13:28:33 -070073void BaseRenderNodeAnimator::setDuration(nsecs_t duration) {
John Reck68bfe0a2014-06-24 15:34:58 -070074 checkMutable();
Alan Viverettead2f8e32014-05-16 13:28:33 -070075 mDuration = duration;
76}
77
78void BaseRenderNodeAnimator::setStartDelay(nsecs_t startDelay) {
John Reck68bfe0a2014-06-24 15:34:58 -070079 checkMutable();
Alan Viverettead2f8e32014-05-16 13:28:33 -070080 mStartDelay = startDelay;
81}
82
John Reck8d8af3c2014-07-01 15:23:45 -070083void BaseRenderNodeAnimator::attach(RenderNode* target) {
Doris Liu8b083202016-02-19 21:46:06 +000084 mStagingTarget = target;
John Reck8d8af3c2014-07-01 15:23:45 -070085 onAttached();
86}
87
Doris Liuc4bb1852016-02-19 21:39:21 +000088void BaseRenderNodeAnimator::start() {
89 mStagingPlayState = PlayState::Running;
90 mStagingRequests.push_back(Request::Start);
91 onStagingPlayStateChanged();
92}
93
94void BaseRenderNodeAnimator::cancel() {
95 mStagingPlayState = PlayState::Finished;
96 mStagingRequests.push_back(Request::Cancel);
97 onStagingPlayStateChanged();
98}
99
100void BaseRenderNodeAnimator::reset() {
101 mStagingPlayState = PlayState::Finished;
102 mStagingRequests.push_back(Request::Reset);
103 onStagingPlayStateChanged();
104}
105
106void BaseRenderNodeAnimator::reverse() {
107 mStagingPlayState = PlayState::Reversing;
108 mStagingRequests.push_back(Request::Reverse);
109 onStagingPlayStateChanged();
110}
111
112void BaseRenderNodeAnimator::end() {
113 mStagingPlayState = PlayState::Finished;
114 mStagingRequests.push_back(Request::End);
115 onStagingPlayStateChanged();
116}
117
118void BaseRenderNodeAnimator::resolveStagingRequest(Request request) {
119 switch (request) {
John Reck1bcacfd2017-11-03 10:12:19 -0700120 case Request::Start:
121 mPlayTime = (mPlayState == PlayState::Running || mPlayState == PlayState::Reversing)
122 ? mPlayTime
123 : 0;
124 mPlayState = PlayState::Running;
125 mPendingActionUponFinish = Action::None;
126 break;
127 case Request::Reverse:
128 mPlayTime = (mPlayState == PlayState::Running || mPlayState == PlayState::Reversing)
129 ? mPlayTime
130 : mDuration;
131 mPlayState = PlayState::Reversing;
132 mPendingActionUponFinish = Action::None;
133 break;
134 case Request::Reset:
135 mPlayTime = 0;
136 mPlayState = PlayState::Finished;
137 mPendingActionUponFinish = Action::Reset;
138 break;
139 case Request::Cancel:
140 mPlayState = PlayState::Finished;
141 mPendingActionUponFinish = Action::None;
142 break;
143 case Request::End:
144 mPlayTime = mPlayState == PlayState::Reversing ? 0 : mDuration;
145 mPlayState = PlayState::Finished;
146 mPendingActionUponFinish = Action::End;
147 break;
148 default:
149 LOG_ALWAYS_FATAL("Invalid staging request: %d", static_cast<int>(request));
Doris Liuc4bb1852016-02-19 21:39:21 +0000150 };
151}
152
John Reck119907c2014-08-14 09:02:01 -0700153void BaseRenderNodeAnimator::pushStaging(AnimationContext& context) {
Doris Liu8b083202016-02-19 21:46:06 +0000154 if (mStagingTarget) {
155 RenderNode* oldTarget = mTarget;
156 mTarget = mStagingTarget;
157 mStagingTarget = nullptr;
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +0100158#ifdef __ANDROID__ // Layoutlib does not support RenderNode
Doris Liu8b083202016-02-19 21:46:06 +0000159 if (oldTarget && oldTarget != mTarget) {
160 oldTarget->onAnimatorTargetChanged(this);
161 }
Jerome Gaillard21e7e2d2019-05-14 14:34:46 +0100162#endif
Doris Liu8b083202016-02-19 21:46:06 +0000163 }
164
John Reck68bfe0a2014-06-24 15:34:58 -0700165 if (!mHasStartValue) {
John Reck8d8af3c2014-07-01 15:23:45 -0700166 doSetStartValue(getValue(mTarget));
Alan Viverettead2f8e32014-05-16 13:28:33 -0700167 }
Doris Liuc4bb1852016-02-19 21:39:21 +0000168
169 if (!mStagingRequests.empty()) {
Doris Liu148f57f2016-02-19 17:19:24 -0800170 // No interpolator was set, use the default
171 if (mPlayState == PlayState::NotStarted && !mInterpolator) {
172 mInterpolator.reset(Interpolator::createDefaultInterpolator());
173 }
Doris Liuc4bb1852016-02-19 21:39:21 +0000174 // Keep track of the play state and play time before they are changed when
175 // staging requests are resolved.
176 nsecs_t currentPlayTime = mPlayTime;
177 PlayState prevFramePlayState = mPlayState;
178
179 // Resolve staging requests one by one.
180 for (Request request : mStagingRequests) {
181 resolveStagingRequest(request);
Doris Liu766431a2016-02-04 22:17:11 +0000182 }
Doris Liuc4bb1852016-02-19 21:39:21 +0000183 mStagingRequests.clear();
184
185 if (mStagingPlayState == PlayState::Finished) {
John Reck4d2c4722014-08-29 10:40:56 -0700186 callOnFinishedListener(context);
John Reck1bcacfd2017-11-03 10:12:19 -0700187 } else if (mStagingPlayState == PlayState::Running ||
188 mStagingPlayState == PlayState::Reversing) {
Doris Liuc4bb1852016-02-19 21:39:21 +0000189 bool changed = currentPlayTime != mPlayTime || prevFramePlayState != mStagingPlayState;
190 if (prevFramePlayState != mStagingPlayState) {
191 transitionToRunning(context);
192 }
193 if (changed) {
194 // Now we need to seek to the stagingPlayTime (i.e. the animation progress that was
195 // requested from UI thread). It is achieved by modifying mStartTime, such that
196 // current time - mStartTime = stagingPlayTime (or mDuration -stagingPlayTime in the
197 // case of reversing)
198 nsecs_t currentFrameTime = context.frameTimeMs();
199 if (mPlayState == PlayState::Reversing) {
200 // Reverse is not supported for animations with a start delay, so here we
201 // assume no start delay.
John Reck1bcacfd2017-11-03 10:12:19 -0700202 mStartTime = currentFrameTime - (mDuration - mPlayTime);
Doris Liuc4bb1852016-02-19 21:39:21 +0000203 } else {
204 // Animation should play forward
205 if (mPlayTime == 0) {
206 // If the request is to start from the beginning, include start delay.
207 mStartTime = currentFrameTime + mStartDelay;
208 } else {
209 // If the request is to seek to a non-zero play time, then we skip start
210 // delay.
211 mStartTime = currentFrameTime - mPlayTime;
212 }
213 }
214 }
John Recke45b1fd2014-04-15 09:50:16 -0700215 }
John Recke45b1fd2014-04-15 09:50:16 -0700216 }
Doris Liu8b083202016-02-19 21:46:06 +0000217 onPushStaging();
John Reck68bfe0a2014-06-24 15:34:58 -0700218}
219
John Reck119907c2014-08-14 09:02:01 -0700220void BaseRenderNodeAnimator::transitionToRunning(AnimationContext& context) {
221 nsecs_t frameTimeMs = context.frameTimeMs();
222 LOG_ALWAYS_FATAL_IF(frameTimeMs <= 0, "%" PRId64 " isn't a real frame time!", frameTimeMs);
John Reck68bfe0a2014-06-24 15:34:58 -0700223 if (mStartDelay < 0 || mStartDelay > 50000) {
224 ALOGW("Your start delay is strange and confusing: %" PRId64, mStartDelay);
225 }
John Reck119907c2014-08-14 09:02:01 -0700226 mStartTime = frameTimeMs + mStartDelay;
John Reck68bfe0a2014-06-24 15:34:58 -0700227 if (mStartTime < 0) {
John Reck1bcacfd2017-11-03 10:12:19 -0700228 ALOGW("Ended up with a really weird start time of %" PRId64 " with frame time %" PRId64
229 " and start delay %" PRId64,
230 mStartTime, frameTimeMs, mStartDelay);
John Reck68bfe0a2014-06-24 15:34:58 -0700231 // Set to 0 so that the animate() basically instantly finishes
232 mStartTime = 0;
233 }
Doris Liu952670d2016-04-12 17:43:00 -0700234 if (mDuration < 0) {
John Reck68bfe0a2014-06-24 15:34:58 -0700235 ALOGW("Your duration is strange and confusing: %" PRId64, mDuration);
236 }
237}
238
John Reck119907c2014-08-14 09:02:01 -0700239bool BaseRenderNodeAnimator::animate(AnimationContext& context) {
Chris Craikb9ce116d2015-08-20 15:14:06 -0700240 if (mPlayState < PlayState::Running) {
John Reck68bfe0a2014-06-24 15:34:58 -0700241 return false;
242 }
Chris Craikb9ce116d2015-08-20 15:14:06 -0700243 if (mPlayState == PlayState::Finished) {
Doris Liu6725d582016-08-04 13:20:17 -0700244 if (mPendingActionUponFinish == Action::Reset) {
245 // Skip to start.
246 updatePlayTime(0);
247 } else if (mPendingActionUponFinish == Action::End) {
248 // Skip to end.
249 updatePlayTime(mDuration);
250 }
251 // Reset pending action.
John Reck1bcacfd2017-11-03 10:12:19 -0700252 mPendingActionUponFinish = Action::None;
John Reck32fb6302014-07-07 09:50:32 -0700253 return true;
254 }
John Reck68bfe0a2014-06-24 15:34:58 -0700255
Doris Liu766431a2016-02-04 22:17:11 +0000256 // This should be set before setValue() so animators can query this time when setValue
257 // is called.
Doris Liuc4bb1852016-02-19 21:39:21 +0000258 nsecs_t currentPlayTime = context.frameTimeMs() - mStartTime;
259 bool finished = updatePlayTime(currentPlayTime);
260 if (finished && mPlayState != PlayState::Finished) {
261 mPlayState = PlayState::Finished;
262 callOnFinishedListener(context);
263 }
264 return finished;
265}
Doris Liu766431a2016-02-04 22:17:11 +0000266
Doris Liuc4bb1852016-02-19 21:39:21 +0000267bool BaseRenderNodeAnimator::updatePlayTime(nsecs_t playTime) {
268 mPlayTime = mPlayState == PlayState::Reversing ? mDuration - playTime : playTime;
269 onPlayTimeChanged(mPlayTime);
John Reck8d8af3c2014-07-01 15:23:45 -0700270 // If BaseRenderNodeAnimator is handling the delay (not typical), then
271 // because the staging properties reflect the final value, we always need
272 // to call setValue even if the animation isn't yet running or is still
273 // being delayed as we need to override the staging value
Doris Liuc4bb1852016-02-19 21:39:21 +0000274 if (playTime < 0) {
John Reck8d8af3c2014-07-01 15:23:45 -0700275 setValue(mTarget, mFromValue);
John Reck68bfe0a2014-06-24 15:34:58 -0700276 return false;
277 }
John Recke45b1fd2014-04-15 09:50:16 -0700278
279 float fraction = 1.0f;
Doris Liuc4bb1852016-02-19 21:39:21 +0000280 if ((mPlayState == PlayState::Running || mPlayState == PlayState::Reversing) && mDuration > 0) {
John Reck1bcacfd2017-11-03 10:12:19 -0700281 fraction = mPlayTime / (float)mDuration;
John Recke45b1fd2014-04-15 09:50:16 -0700282 }
Doris Liuc4bb1852016-02-19 21:39:21 +0000283 fraction = MathUtils::clamp(fraction, 0.0f, 1.0f);
John Reck68bfe0a2014-06-24 15:34:58 -0700284
John Recke45b1fd2014-04-15 09:50:16 -0700285 fraction = mInterpolator->interpolate(fraction);
John Reck8d8af3c2014-07-01 15:23:45 -0700286 setValue(mTarget, mFromValue + (mDeltaValue * fraction));
John Recke45b1fd2014-04-15 09:50:16 -0700287
Doris Liuc4bb1852016-02-19 21:39:21 +0000288 return playTime >= mDuration;
John Recke45b1fd2014-04-15 09:50:16 -0700289}
290
Doris Liu718cd3e2016-05-17 16:50:31 -0700291nsecs_t BaseRenderNodeAnimator::getRemainingPlayTime() {
292 return mPlayState == PlayState::Reversing ? mPlayTime : mDuration - mPlayTime;
293}
294
John Recke2478d42014-09-03 16:46:05 -0700295void BaseRenderNodeAnimator::forceEndNow(AnimationContext& context) {
Chris Craikb9ce116d2015-08-20 15:14:06 -0700296 if (mPlayState < PlayState::Finished) {
297 mPlayState = PlayState::Finished;
John Recke2478d42014-09-03 16:46:05 -0700298 callOnFinishedListener(context);
299 }
300}
301
John Reck119907c2014-08-14 09:02:01 -0700302void BaseRenderNodeAnimator::callOnFinishedListener(AnimationContext& context) {
John Reck52244ff2014-05-01 21:27:37 -0700303 if (mListener.get()) {
John Reck119907c2014-08-14 09:02:01 -0700304 context.callOnFinished(this, mListener.get());
John Reck52244ff2014-05-01 21:27:37 -0700305 }
306}
307
308/************************************************************
John Recke45b1fd2014-04-15 09:50:16 -0700309 * RenderPropertyAnimator
310 ************************************************************/
311
John Reckff941dc2014-05-14 16:34:14 -0700312struct RenderPropertyAnimator::PropertyAccessors {
John Reck1bcacfd2017-11-03 10:12:19 -0700313 RenderNode::DirtyPropertyMask dirtyMask;
314 GetFloatProperty getter;
315 SetFloatProperty setter;
John Reck52244ff2014-05-01 21:27:37 -0700316};
317
John Reckff941dc2014-05-14 16:34:14 -0700318// Maps RenderProperty enum to accessors
319const RenderPropertyAnimator::PropertyAccessors RenderPropertyAnimator::PROPERTY_ACCESSOR_LUT[] = {
John Reck1bcacfd2017-11-03 10:12:19 -0700320 {RenderNode::TRANSLATION_X, &RenderProperties::getTranslationX,
321 &RenderProperties::setTranslationX},
322 {RenderNode::TRANSLATION_Y, &RenderProperties::getTranslationY,
323 &RenderProperties::setTranslationY},
324 {RenderNode::TRANSLATION_Z, &RenderProperties::getTranslationZ,
325 &RenderProperties::setTranslationZ},
326 {RenderNode::SCALE_X, &RenderProperties::getScaleX, &RenderProperties::setScaleX},
327 {RenderNode::SCALE_Y, &RenderProperties::getScaleY, &RenderProperties::setScaleY},
328 {RenderNode::ROTATION, &RenderProperties::getRotation, &RenderProperties::setRotation},
329 {RenderNode::ROTATION_X, &RenderProperties::getRotationX, &RenderProperties::setRotationX},
330 {RenderNode::ROTATION_Y, &RenderProperties::getRotationY, &RenderProperties::setRotationY},
331 {RenderNode::X, &RenderProperties::getX, &RenderProperties::setX},
332 {RenderNode::Y, &RenderProperties::getY, &RenderProperties::setY},
333 {RenderNode::Z, &RenderProperties::getZ, &RenderProperties::setZ},
334 {RenderNode::ALPHA, &RenderProperties::getAlpha, &RenderProperties::setAlpha},
John Reckff941dc2014-05-14 16:34:14 -0700335};
336
337RenderPropertyAnimator::RenderPropertyAnimator(RenderProperty property, float finalValue)
John Reck1bcacfd2017-11-03 10:12:19 -0700338 : BaseRenderNodeAnimator(finalValue), mPropertyAccess(&(PROPERTY_ACCESSOR_LUT[property])) {}
John Recke45b1fd2014-04-15 09:50:16 -0700339
John Reck8d8af3c2014-07-01 15:23:45 -0700340void RenderPropertyAnimator::onAttached() {
John Reck1bcacfd2017-11-03 10:12:19 -0700341 if (!mHasStartValue && mStagingTarget->isPropertyFieldDirty(mPropertyAccess->dirtyMask)) {
Doris Liu8b083202016-02-19 21:46:06 +0000342 setStartValue((mStagingTarget->stagingProperties().*mPropertyAccess->getter)());
John Reckff941dc2014-05-14 16:34:14 -0700343 }
John Reck8d8af3c2014-07-01 15:23:45 -0700344}
345
346void RenderPropertyAnimator::onStagingPlayStateChanged() {
Chris Craikb9ce116d2015-08-20 15:14:06 -0700347 if (mStagingPlayState == PlayState::Running) {
Doris Liu8b083202016-02-19 21:46:06 +0000348 if (mStagingTarget) {
349 (mStagingTarget->mutateStagingProperties().*mPropertyAccess->setter)(finalValue());
350 } else {
351 // In the case of start delay where stagingTarget has been sync'ed over and null'ed
352 // we delay the properties update to push staging.
353 mShouldUpdateStagingProperties = true;
354 }
Chris Craikb9ce116d2015-08-20 15:14:06 -0700355 } else if (mStagingPlayState == PlayState::Finished) {
John Reck32fb6302014-07-07 09:50:32 -0700356 // We're being canceled, so make sure that whatever values the UI thread
357 // is observing for us is pushed over
Doris Liu8b083202016-02-19 21:46:06 +0000358 mShouldSyncPropertyFields = true;
359 }
360}
361
362void RenderPropertyAnimator::onPushStaging() {
363 if (mShouldUpdateStagingProperties) {
364 (mTarget->mutateStagingProperties().*mPropertyAccess->setter)(finalValue());
365 mShouldUpdateStagingProperties = false;
366 }
367
368 if (mShouldSyncPropertyFields) {
John Reck32fb6302014-07-07 09:50:32 -0700369 mTarget->setPropertyFieldsDirty(dirtyMask());
Doris Liu8b083202016-02-19 21:46:06 +0000370 mShouldSyncPropertyFields = false;
John Reck8d8af3c2014-07-01 15:23:45 -0700371 }
John Recke45b1fd2014-04-15 09:50:16 -0700372}
373
John Reck22184722014-06-20 07:19:30 -0700374uint32_t RenderPropertyAnimator::dirtyMask() {
375 return mPropertyAccess->dirtyMask;
376}
377
John Reckff941dc2014-05-14 16:34:14 -0700378float RenderPropertyAnimator::getValue(RenderNode* target) const {
379 return (target->properties().*mPropertyAccess->getter)();
380}
381
382void RenderPropertyAnimator::setValue(RenderNode* target, float value) {
383 (target->animatorProperties().*mPropertyAccess->setter)(value);
John Recke45b1fd2014-04-15 09:50:16 -0700384}
385
John Reck52244ff2014-05-01 21:27:37 -0700386/************************************************************
387 * CanvasPropertyPrimitiveAnimator
388 ************************************************************/
John Recke45b1fd2014-04-15 09:50:16 -0700389
John Reck1bcacfd2017-11-03 10:12:19 -0700390CanvasPropertyPrimitiveAnimator::CanvasPropertyPrimitiveAnimator(CanvasPropertyPrimitive* property,
391 float finalValue)
392 : BaseRenderNodeAnimator(finalValue), mProperty(property) {}
John Reck52244ff2014-05-01 21:27:37 -0700393
Andreas Gampe64bb4132014-11-22 00:35:09 +0000394float CanvasPropertyPrimitiveAnimator::getValue(RenderNode* target) const {
John Reck52244ff2014-05-01 21:27:37 -0700395 return mProperty->value;
396}
397
Andreas Gampe64bb4132014-11-22 00:35:09 +0000398void CanvasPropertyPrimitiveAnimator::setValue(RenderNode* target, float value) {
John Reck52244ff2014-05-01 21:27:37 -0700399 mProperty->value = value;
400}
401
John Recka7c2ea22014-08-08 13:21:00 -0700402uint32_t CanvasPropertyPrimitiveAnimator::dirtyMask() {
403 return RenderNode::DISPLAY_LIST;
404}
405
John Reck52244ff2014-05-01 21:27:37 -0700406/************************************************************
407 * CanvasPropertySkPaintAnimator
408 ************************************************************/
409
John Reck1bcacfd2017-11-03 10:12:19 -0700410CanvasPropertyPaintAnimator::CanvasPropertyPaintAnimator(CanvasPropertyPaint* property,
411 PaintField field, float finalValue)
412 : BaseRenderNodeAnimator(finalValue), mProperty(property), mField(field) {}
John Reck52244ff2014-05-01 21:27:37 -0700413
Andreas Gampe64bb4132014-11-22 00:35:09 +0000414float CanvasPropertyPaintAnimator::getValue(RenderNode* target) const {
John Reck52244ff2014-05-01 21:27:37 -0700415 switch (mField) {
John Reck1bcacfd2017-11-03 10:12:19 -0700416 case STROKE_WIDTH:
417 return mProperty->value.getStrokeWidth();
418 case ALPHA:
419 return mProperty->value.getAlpha();
John Recke45b1fd2014-04-15 09:50:16 -0700420 }
John Reck1bcacfd2017-11-03 10:12:19 -0700421 LOG_ALWAYS_FATAL("Unknown field %d", (int)mField);
John Reck52244ff2014-05-01 21:27:37 -0700422 return -1;
John Recke45b1fd2014-04-15 09:50:16 -0700423}
424
John Reck531ee702014-05-13 10:06:08 -0700425static uint8_t to_uint8(float value) {
John Reck1bcacfd2017-11-03 10:12:19 -0700426 int c = (int)(value + .5f);
427 return static_cast<uint8_t>(c < 0 ? 0 : c > 255 ? 255 : c);
John Reck531ee702014-05-13 10:06:08 -0700428}
429
Andreas Gampe64bb4132014-11-22 00:35:09 +0000430void CanvasPropertyPaintAnimator::setValue(RenderNode* target, float value) {
John Reck52244ff2014-05-01 21:27:37 -0700431 switch (mField) {
John Reck1bcacfd2017-11-03 10:12:19 -0700432 case STROKE_WIDTH:
433 mProperty->value.setStrokeWidth(value);
434 return;
435 case ALPHA:
436 mProperty->value.setAlpha(to_uint8(value));
437 return;
John Reck52244ff2014-05-01 21:27:37 -0700438 }
John Reck1bcacfd2017-11-03 10:12:19 -0700439 LOG_ALWAYS_FATAL("Unknown field %d", (int)mField);
John Recke45b1fd2014-04-15 09:50:16 -0700440}
441
John Recka7c2ea22014-08-08 13:21:00 -0700442uint32_t CanvasPropertyPaintAnimator::dirtyMask() {
443 return RenderNode::DISPLAY_LIST;
444}
445
John Reck1bcacfd2017-11-03 10:12:19 -0700446RevealAnimator::RevealAnimator(int centerX, int centerY, float startValue, float finalValue)
447 : BaseRenderNodeAnimator(finalValue), mCenterX(centerX), mCenterY(centerY) {
John Reckd3de42c2014-07-15 14:29:33 -0700448 setStartValue(startValue);
449}
450
451float RevealAnimator::getValue(RenderNode* target) const {
Chris Craikaf4d04c2014-07-29 12:50:14 -0700452 return target->properties().getRevealClip().getRadius();
John Reckd3de42c2014-07-15 14:29:33 -0700453}
454
455void RevealAnimator::setValue(RenderNode* target, float value) {
John Reck1bcacfd2017-11-03 10:12:19 -0700456 target->animatorProperties().mutableRevealClip().set(true, mCenterX, mCenterY, value);
John Reckd3de42c2014-07-15 14:29:33 -0700457}
458
John Recka7c2ea22014-08-08 13:21:00 -0700459uint32_t RevealAnimator::dirtyMask() {
460 return RenderNode::GENERIC;
461}
462
John Recke45b1fd2014-04-15 09:50:16 -0700463} /* namespace uirenderer */
464} /* namespace android */