blob: 372bcb3b237515804f0d18951dbd7b056d09e5e8 [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)
John Reck8d8af3c2014-07-01 15:23:45 -070036 , mFinalValue(finalValue)
John Reckff941dc2014-05-14 16:34:14 -070037 , mDeltaValue(0)
38 , mFromValue(0)
Chris Craikb9ce116d2015-08-20 15:14:06 -070039 , mStagingPlayState(PlayState::NotStarted)
40 , mPlayState(PlayState::NotStarted)
John Reck68bfe0a2014-06-24 15:34:58 -070041 , mHasStartValue(false)
John Recke45b1fd2014-04-15 09:50:16 -070042 , mStartTime(0)
Alan Viverettead2f8e32014-05-16 13:28:33 -070043 , mDuration(300)
Chris Craik572d9ac2014-09-12 17:40:20 -070044 , mStartDelay(0)
Doris Liuc4bb1852016-02-19 21:39:21 +000045 , mMayRunAsync(true)
46 , mPlayTime(0) {
John Recke45b1fd2014-04-15 09:50:16 -070047}
48
John Reckff941dc2014-05-14 16:34:14 -070049BaseRenderNodeAnimator::~BaseRenderNodeAnimator() {
John Reck68bfe0a2014-06-24 15:34:58 -070050}
51
52void BaseRenderNodeAnimator::checkMutable() {
53 // Should be impossible to hit as the Java-side also has guards for this
Chris Craikb9ce116d2015-08-20 15:14:06 -070054 LOG_ALWAYS_FATAL_IF(mStagingPlayState != PlayState::NotStarted,
John Reck68bfe0a2014-06-24 15:34:58 -070055 "Animator has already been started!");
John Recke45b1fd2014-04-15 09:50:16 -070056}
57
John Reckff941dc2014-05-14 16:34:14 -070058void BaseRenderNodeAnimator::setInterpolator(Interpolator* interpolator) {
John Reck68bfe0a2014-06-24 15:34:58 -070059 checkMutable();
Chris Craik51d6a3d2014-12-22 17:16:56 -080060 mInterpolator.reset(interpolator);
John Recke45b1fd2014-04-15 09:50:16 -070061}
62
John Reckff941dc2014-05-14 16:34:14 -070063void BaseRenderNodeAnimator::setStartValue(float value) {
John Reck68bfe0a2014-06-24 15:34:58 -070064 checkMutable();
65 doSetStartValue(value);
John Reckff941dc2014-05-14 16:34:14 -070066}
67
John Reck68bfe0a2014-06-24 15:34:58 -070068void BaseRenderNodeAnimator::doSetStartValue(float value) {
69 mFromValue = value;
70 mDeltaValue = (mFinalValue - mFromValue);
71 mHasStartValue = true;
John Reckff941dc2014-05-14 16:34:14 -070072}
73
Alan Viverettead2f8e32014-05-16 13:28:33 -070074void BaseRenderNodeAnimator::setDuration(nsecs_t duration) {
John Reck68bfe0a2014-06-24 15:34:58 -070075 checkMutable();
Alan Viverettead2f8e32014-05-16 13:28:33 -070076 mDuration = duration;
77}
78
79void BaseRenderNodeAnimator::setStartDelay(nsecs_t startDelay) {
John Reck68bfe0a2014-06-24 15:34:58 -070080 checkMutable();
Alan Viverettead2f8e32014-05-16 13:28:33 -070081 mStartDelay = startDelay;
82}
83
John Reck8d8af3c2014-07-01 15:23:45 -070084void BaseRenderNodeAnimator::attach(RenderNode* target) {
85 mTarget = target;
86 onAttached();
87}
88
Doris Liuc4bb1852016-02-19 21:39:21 +000089void BaseRenderNodeAnimator::start() {
90 mStagingPlayState = PlayState::Running;
91 mStagingRequests.push_back(Request::Start);
92 onStagingPlayStateChanged();
93}
94
95void BaseRenderNodeAnimator::cancel() {
96 mStagingPlayState = PlayState::Finished;
97 mStagingRequests.push_back(Request::Cancel);
98 onStagingPlayStateChanged();
99}
100
101void BaseRenderNodeAnimator::reset() {
102 mStagingPlayState = PlayState::Finished;
103 mStagingRequests.push_back(Request::Reset);
104 onStagingPlayStateChanged();
105}
106
107void BaseRenderNodeAnimator::reverse() {
108 mStagingPlayState = PlayState::Reversing;
109 mStagingRequests.push_back(Request::Reverse);
110 onStagingPlayStateChanged();
111}
112
113void BaseRenderNodeAnimator::end() {
114 mStagingPlayState = PlayState::Finished;
115 mStagingRequests.push_back(Request::End);
116 onStagingPlayStateChanged();
117}
118
119void BaseRenderNodeAnimator::resolveStagingRequest(Request request) {
120 switch (request) {
121 case Request::Start:
122 mPlayTime = (mPlayState == PlayState::Running || mPlayState == PlayState::Reversing) ?
123 mPlayTime : 0;
124 mPlayState = PlayState::Running;
125 break;
126 case Request::Reverse:
127 mPlayTime = (mPlayState == PlayState::Running || mPlayState == PlayState::Reversing) ?
128 mPlayTime : mDuration;
129 mPlayState = PlayState::Reversing;
130 break;
131 case Request::Reset:
132 mPlayTime = 0;
133 mPlayState = PlayState::Finished;
134 break;
135 case Request::Cancel:
136 mPlayState = PlayState::Finished;
137 break;
138 case Request::End:
139 mPlayTime = mPlayState == PlayState::Reversing ? 0 : mDuration;
140 mPlayState = PlayState::Finished;
141 break;
142 default:
143 LOG_ALWAYS_FATAL("Invalid staging request: %d", static_cast<int>(request));
144 };
145}
146
John Reck119907c2014-08-14 09:02:01 -0700147void BaseRenderNodeAnimator::pushStaging(AnimationContext& context) {
John Reck68bfe0a2014-06-24 15:34:58 -0700148 if (!mHasStartValue) {
John Reck8d8af3c2014-07-01 15:23:45 -0700149 doSetStartValue(getValue(mTarget));
Alan Viverettead2f8e32014-05-16 13:28:33 -0700150 }
Doris Liuc4bb1852016-02-19 21:39:21 +0000151
152 if (!mStagingRequests.empty()) {
153 // Keep track of the play state and play time before they are changed when
154 // staging requests are resolved.
155 nsecs_t currentPlayTime = mPlayTime;
156 PlayState prevFramePlayState = mPlayState;
157
158 // Resolve staging requests one by one.
159 for (Request request : mStagingRequests) {
160 resolveStagingRequest(request);
Doris Liu766431a2016-02-04 22:17:11 +0000161 }
Doris Liuc4bb1852016-02-19 21:39:21 +0000162 mStagingRequests.clear();
163
164 if (mStagingPlayState == PlayState::Finished) {
165 // Set the staging play time and end the animation
166 updatePlayTime(mPlayTime);
John Reck4d2c4722014-08-29 10:40:56 -0700167 callOnFinishedListener(context);
Doris Liuc4bb1852016-02-19 21:39:21 +0000168 } else if (mStagingPlayState == PlayState::Running
169 || mStagingPlayState == PlayState::Reversing) {
170 bool changed = currentPlayTime != mPlayTime || prevFramePlayState != mStagingPlayState;
171 if (prevFramePlayState != mStagingPlayState) {
172 transitionToRunning(context);
173 }
174 if (changed) {
175 // Now we need to seek to the stagingPlayTime (i.e. the animation progress that was
176 // requested from UI thread). It is achieved by modifying mStartTime, such that
177 // current time - mStartTime = stagingPlayTime (or mDuration -stagingPlayTime in the
178 // case of reversing)
179 nsecs_t currentFrameTime = context.frameTimeMs();
180 if (mPlayState == PlayState::Reversing) {
181 // Reverse is not supported for animations with a start delay, so here we
182 // assume no start delay.
183 mStartTime = currentFrameTime - (mDuration - mPlayTime);
184 } else {
185 // Animation should play forward
186 if (mPlayTime == 0) {
187 // If the request is to start from the beginning, include start delay.
188 mStartTime = currentFrameTime + mStartDelay;
189 } else {
190 // If the request is to seek to a non-zero play time, then we skip start
191 // delay.
192 mStartTime = currentFrameTime - mPlayTime;
193 }
194 }
195 }
John Recke45b1fd2014-04-15 09:50:16 -0700196 }
John Recke45b1fd2014-04-15 09:50:16 -0700197 }
John Reck68bfe0a2014-06-24 15:34:58 -0700198}
199
John Reck119907c2014-08-14 09:02:01 -0700200void BaseRenderNodeAnimator::transitionToRunning(AnimationContext& context) {
201 nsecs_t frameTimeMs = context.frameTimeMs();
202 LOG_ALWAYS_FATAL_IF(frameTimeMs <= 0, "%" PRId64 " isn't a real frame time!", frameTimeMs);
John Reck68bfe0a2014-06-24 15:34:58 -0700203 if (mStartDelay < 0 || mStartDelay > 50000) {
204 ALOGW("Your start delay is strange and confusing: %" PRId64, mStartDelay);
205 }
John Reck119907c2014-08-14 09:02:01 -0700206 mStartTime = frameTimeMs + mStartDelay;
John Reck68bfe0a2014-06-24 15:34:58 -0700207 if (mStartTime < 0) {
208 ALOGW("Ended up with a really weird start time of %" PRId64
209 " with frame time %" PRId64 " and start delay %" PRId64,
John Reck119907c2014-08-14 09:02:01 -0700210 mStartTime, frameTimeMs, mStartDelay);
John Reck68bfe0a2014-06-24 15:34:58 -0700211 // Set to 0 so that the animate() basically instantly finishes
212 mStartTime = 0;
213 }
214 // No interpolator was set, use the default
215 if (!mInterpolator) {
Chris Craik51d6a3d2014-12-22 17:16:56 -0800216 mInterpolator.reset(Interpolator::createDefaultInterpolator());
John Reck68bfe0a2014-06-24 15:34:58 -0700217 }
218 if (mDuration < 0 || mDuration > 50000) {
219 ALOGW("Your duration is strange and confusing: %" PRId64, mDuration);
220 }
221}
222
John Reck119907c2014-08-14 09:02:01 -0700223bool BaseRenderNodeAnimator::animate(AnimationContext& context) {
Chris Craikb9ce116d2015-08-20 15:14:06 -0700224 if (mPlayState < PlayState::Running) {
John Reck68bfe0a2014-06-24 15:34:58 -0700225 return false;
226 }
Chris Craikb9ce116d2015-08-20 15:14:06 -0700227 if (mPlayState == PlayState::Finished) {
John Reck32fb6302014-07-07 09:50:32 -0700228 return true;
229 }
John Reck68bfe0a2014-06-24 15:34:58 -0700230
Doris Liu766431a2016-02-04 22:17:11 +0000231 // This should be set before setValue() so animators can query this time when setValue
232 // is called.
Doris Liuc4bb1852016-02-19 21:39:21 +0000233 nsecs_t currentPlayTime = context.frameTimeMs() - mStartTime;
234 bool finished = updatePlayTime(currentPlayTime);
235 if (finished && mPlayState != PlayState::Finished) {
236 mPlayState = PlayState::Finished;
237 callOnFinishedListener(context);
238 }
239 return finished;
240}
Doris Liu766431a2016-02-04 22:17:11 +0000241
Doris Liuc4bb1852016-02-19 21:39:21 +0000242bool BaseRenderNodeAnimator::updatePlayTime(nsecs_t playTime) {
243 mPlayTime = mPlayState == PlayState::Reversing ? mDuration - playTime : playTime;
244 onPlayTimeChanged(mPlayTime);
John Reck8d8af3c2014-07-01 15:23:45 -0700245 // If BaseRenderNodeAnimator is handling the delay (not typical), then
246 // because the staging properties reflect the final value, we always need
247 // to call setValue even if the animation isn't yet running or is still
248 // being delayed as we need to override the staging value
Doris Liuc4bb1852016-02-19 21:39:21 +0000249 if (playTime < 0) {
John Reck8d8af3c2014-07-01 15:23:45 -0700250 setValue(mTarget, mFromValue);
John Reck68bfe0a2014-06-24 15:34:58 -0700251 return false;
252 }
John Recke45b1fd2014-04-15 09:50:16 -0700253
254 float fraction = 1.0f;
Doris Liuc4bb1852016-02-19 21:39:21 +0000255 if ((mPlayState == PlayState::Running || mPlayState == PlayState::Reversing) && mDuration > 0) {
256 fraction = mPlayTime / (float) mDuration;
John Recke45b1fd2014-04-15 09:50:16 -0700257 }
Doris Liuc4bb1852016-02-19 21:39:21 +0000258 fraction = MathUtils::clamp(fraction, 0.0f, 1.0f);
John Reck68bfe0a2014-06-24 15:34:58 -0700259
John Recke45b1fd2014-04-15 09:50:16 -0700260 fraction = mInterpolator->interpolate(fraction);
John Reck8d8af3c2014-07-01 15:23:45 -0700261 setValue(mTarget, mFromValue + (mDeltaValue * fraction));
John Recke45b1fd2014-04-15 09:50:16 -0700262
Doris Liuc4bb1852016-02-19 21:39:21 +0000263 return playTime >= mDuration;
John Recke45b1fd2014-04-15 09:50:16 -0700264}
265
John Recke2478d42014-09-03 16:46:05 -0700266void BaseRenderNodeAnimator::forceEndNow(AnimationContext& context) {
Chris Craikb9ce116d2015-08-20 15:14:06 -0700267 if (mPlayState < PlayState::Finished) {
268 mPlayState = PlayState::Finished;
John Recke2478d42014-09-03 16:46:05 -0700269 callOnFinishedListener(context);
270 }
271}
272
John Reck119907c2014-08-14 09:02:01 -0700273void BaseRenderNodeAnimator::callOnFinishedListener(AnimationContext& context) {
John Reck52244ff2014-05-01 21:27:37 -0700274 if (mListener.get()) {
John Reck119907c2014-08-14 09:02:01 -0700275 context.callOnFinished(this, mListener.get());
John Reck52244ff2014-05-01 21:27:37 -0700276 }
277}
278
279/************************************************************
John Recke45b1fd2014-04-15 09:50:16 -0700280 * RenderPropertyAnimator
281 ************************************************************/
282
John Reckff941dc2014-05-14 16:34:14 -0700283struct RenderPropertyAnimator::PropertyAccessors {
284 RenderNode::DirtyPropertyMask dirtyMask;
285 GetFloatProperty getter;
286 SetFloatProperty setter;
John Reck52244ff2014-05-01 21:27:37 -0700287};
288
John Reckff941dc2014-05-14 16:34:14 -0700289// Maps RenderProperty enum to accessors
290const RenderPropertyAnimator::PropertyAccessors RenderPropertyAnimator::PROPERTY_ACCESSOR_LUT[] = {
291 {RenderNode::TRANSLATION_X, &RenderProperties::getTranslationX, &RenderProperties::setTranslationX },
292 {RenderNode::TRANSLATION_Y, &RenderProperties::getTranslationY, &RenderProperties::setTranslationY },
293 {RenderNode::TRANSLATION_X, &RenderProperties::getTranslationZ, &RenderProperties::setTranslationZ },
294 {RenderNode::SCALE_X, &RenderProperties::getScaleX, &RenderProperties::setScaleX },
295 {RenderNode::SCALE_Y, &RenderProperties::getScaleY, &RenderProperties::setScaleY },
296 {RenderNode::ROTATION, &RenderProperties::getRotation, &RenderProperties::setRotation },
297 {RenderNode::ROTATION_X, &RenderProperties::getRotationX, &RenderProperties::setRotationX },
298 {RenderNode::ROTATION_Y, &RenderProperties::getRotationY, &RenderProperties::setRotationY },
299 {RenderNode::X, &RenderProperties::getX, &RenderProperties::setX },
300 {RenderNode::Y, &RenderProperties::getY, &RenderProperties::setY },
301 {RenderNode::Z, &RenderProperties::getZ, &RenderProperties::setZ },
302 {RenderNode::ALPHA, &RenderProperties::getAlpha, &RenderProperties::setAlpha },
303};
304
305RenderPropertyAnimator::RenderPropertyAnimator(RenderProperty property, float finalValue)
306 : BaseRenderNodeAnimator(finalValue)
307 , mPropertyAccess(&(PROPERTY_ACCESSOR_LUT[property])) {
John Recke45b1fd2014-04-15 09:50:16 -0700308}
309
John Reck8d8af3c2014-07-01 15:23:45 -0700310void RenderPropertyAnimator::onAttached() {
John Reck68bfe0a2014-06-24 15:34:58 -0700311 if (!mHasStartValue
John Reck8d8af3c2014-07-01 15:23:45 -0700312 && mTarget->isPropertyFieldDirty(mPropertyAccess->dirtyMask)) {
313 setStartValue((mTarget->stagingProperties().*mPropertyAccess->getter)());
John Reckff941dc2014-05-14 16:34:14 -0700314 }
John Reck8d8af3c2014-07-01 15:23:45 -0700315}
316
317void RenderPropertyAnimator::onStagingPlayStateChanged() {
Chris Craikb9ce116d2015-08-20 15:14:06 -0700318 if (mStagingPlayState == PlayState::Running) {
John Reck8d8af3c2014-07-01 15:23:45 -0700319 (mTarget->mutateStagingProperties().*mPropertyAccess->setter)(finalValue());
Chris Craikb9ce116d2015-08-20 15:14:06 -0700320 } else if (mStagingPlayState == PlayState::Finished) {
John Reck32fb6302014-07-07 09:50:32 -0700321 // We're being canceled, so make sure that whatever values the UI thread
322 // is observing for us is pushed over
323 mTarget->setPropertyFieldsDirty(dirtyMask());
John Reck8d8af3c2014-07-01 15:23:45 -0700324 }
John Recke45b1fd2014-04-15 09:50:16 -0700325}
326
John Reck22184722014-06-20 07:19:30 -0700327uint32_t RenderPropertyAnimator::dirtyMask() {
328 return mPropertyAccess->dirtyMask;
329}
330
John Reckff941dc2014-05-14 16:34:14 -0700331float RenderPropertyAnimator::getValue(RenderNode* target) const {
332 return (target->properties().*mPropertyAccess->getter)();
333}
334
335void RenderPropertyAnimator::setValue(RenderNode* target, float value) {
336 (target->animatorProperties().*mPropertyAccess->setter)(value);
John Recke45b1fd2014-04-15 09:50:16 -0700337}
338
John Reck52244ff2014-05-01 21:27:37 -0700339/************************************************************
340 * CanvasPropertyPrimitiveAnimator
341 ************************************************************/
John Recke45b1fd2014-04-15 09:50:16 -0700342
John Reck52244ff2014-05-01 21:27:37 -0700343CanvasPropertyPrimitiveAnimator::CanvasPropertyPrimitiveAnimator(
John Reckff941dc2014-05-14 16:34:14 -0700344 CanvasPropertyPrimitive* property, float finalValue)
345 : BaseRenderNodeAnimator(finalValue)
John Reck52244ff2014-05-01 21:27:37 -0700346 , mProperty(property) {
347}
348
Andreas Gampe64bb4132014-11-22 00:35:09 +0000349float CanvasPropertyPrimitiveAnimator::getValue(RenderNode* target) const {
John Reck52244ff2014-05-01 21:27:37 -0700350 return mProperty->value;
351}
352
Andreas Gampe64bb4132014-11-22 00:35:09 +0000353void CanvasPropertyPrimitiveAnimator::setValue(RenderNode* target, float value) {
John Reck52244ff2014-05-01 21:27:37 -0700354 mProperty->value = value;
355}
356
John Recka7c2ea22014-08-08 13:21:00 -0700357uint32_t CanvasPropertyPrimitiveAnimator::dirtyMask() {
358 return RenderNode::DISPLAY_LIST;
359}
360
John Reck52244ff2014-05-01 21:27:37 -0700361/************************************************************
362 * CanvasPropertySkPaintAnimator
363 ************************************************************/
364
365CanvasPropertyPaintAnimator::CanvasPropertyPaintAnimator(
John Reckff941dc2014-05-14 16:34:14 -0700366 CanvasPropertyPaint* property, PaintField field, float finalValue)
367 : BaseRenderNodeAnimator(finalValue)
John Reck52244ff2014-05-01 21:27:37 -0700368 , mProperty(property)
369 , mField(field) {
370}
371
Andreas Gampe64bb4132014-11-22 00:35:09 +0000372float CanvasPropertyPaintAnimator::getValue(RenderNode* target) const {
John Reck52244ff2014-05-01 21:27:37 -0700373 switch (mField) {
374 case STROKE_WIDTH:
375 return mProperty->value.getStrokeWidth();
376 case ALPHA:
377 return mProperty->value.getAlpha();
John Recke45b1fd2014-04-15 09:50:16 -0700378 }
John Reck52244ff2014-05-01 21:27:37 -0700379 LOG_ALWAYS_FATAL("Unknown field %d", (int) mField);
380 return -1;
John Recke45b1fd2014-04-15 09:50:16 -0700381}
382
John Reck531ee702014-05-13 10:06:08 -0700383static uint8_t to_uint8(float value) {
384 int c = (int) (value + .5f);
385 return static_cast<uint8_t>( c < 0 ? 0 : c > 255 ? 255 : c );
386}
387
Andreas Gampe64bb4132014-11-22 00:35:09 +0000388void CanvasPropertyPaintAnimator::setValue(RenderNode* target, float value) {
John Reck52244ff2014-05-01 21:27:37 -0700389 switch (mField) {
390 case STROKE_WIDTH:
391 mProperty->value.setStrokeWidth(value);
392 return;
393 case ALPHA:
John Reck531ee702014-05-13 10:06:08 -0700394 mProperty->value.setAlpha(to_uint8(value));
John Reck52244ff2014-05-01 21:27:37 -0700395 return;
396 }
397 LOG_ALWAYS_FATAL("Unknown field %d", (int) mField);
John Recke45b1fd2014-04-15 09:50:16 -0700398}
399
John Recka7c2ea22014-08-08 13:21:00 -0700400uint32_t CanvasPropertyPaintAnimator::dirtyMask() {
401 return RenderNode::DISPLAY_LIST;
402}
403
Chris Craikaf4d04c2014-07-29 12:50:14 -0700404RevealAnimator::RevealAnimator(int centerX, int centerY,
John Reckd3de42c2014-07-15 14:29:33 -0700405 float startValue, float finalValue)
406 : BaseRenderNodeAnimator(finalValue)
407 , mCenterX(centerX)
Chris Craikaf4d04c2014-07-29 12:50:14 -0700408 , mCenterY(centerY) {
John Reckd3de42c2014-07-15 14:29:33 -0700409 setStartValue(startValue);
410}
411
412float RevealAnimator::getValue(RenderNode* target) const {
Chris Craikaf4d04c2014-07-29 12:50:14 -0700413 return target->properties().getRevealClip().getRadius();
John Reckd3de42c2014-07-15 14:29:33 -0700414}
415
416void RevealAnimator::setValue(RenderNode* target, float value) {
Chris Craikaf4d04c2014-07-29 12:50:14 -0700417 target->animatorProperties().mutableRevealClip().set(true,
John Reckd3de42c2014-07-15 14:29:33 -0700418 mCenterX, mCenterY, value);
419}
420
John Recka7c2ea22014-08-08 13:21:00 -0700421uint32_t RevealAnimator::dirtyMask() {
422 return RenderNode::GENERIC;
423}
424
John Recke45b1fd2014-04-15 09:50:16 -0700425} /* namespace uirenderer */
426} /* namespace android */