1 
2 /*
3  * Copyright 2006 The Android Open Source Project
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8 
9 
10 #include "SkAnimator.h"
11 #include "SkAnimateMaker.h"
12 #include "SkCanvas.h"
13 #include "SkDisplayApply.h"
14 #include "SkDisplayMovie.h"
15 #include "SkDisplayTypes.h"
16 #include "SkDisplayXMLParser.h"
17 #include "SkStream.h"
18 #include "SkScript.h"
19 #include "SkScript2.h" //   compiled script experiment
20 #include "SkSystemEventTypes.h"
21 #include "SkTypedArray.h"
22 #ifdef SK_BUILD_FOR_ANDROID
23 #include "SkDrawExtraPathEffect.h"
24 #endif
25 #ifdef SK_DEBUG
26 #include "SkTime.h"
27 #endif
28 
29 #if defined SK_BUILD_FOR_WIN32 && defined SK_DEBUG
30     #define _static
31     extern const char gMathPrimerText[];
32     extern const char gMathPrimerBinary[];
33 #else
34     #define _static static
35 #endif
36 
37 _static const char gMathPrimerText[] =
38 "<screenplay>"
39     "<Math id=\"Math\"/>"
40     "<Number id=\"Number\"/>"
41 "</screenplay>";
42 
43 #define gMathPrimer gMathPrimerText
44 
SkAnimator()45 SkAnimator::SkAnimator() : fMaker(nullptr) {
46     initialize();
47 }
48 
~SkAnimator()49 SkAnimator::~SkAnimator() { delete fMaker; }
50 
addExtras(SkExtras * extras)51 void SkAnimator::addExtras(SkExtras* extras) {
52     *fMaker->fExtras.append() = extras;
53 }
54 
appendStream(SkStream * stream)55 bool SkAnimator::appendStream(SkStream* stream) {
56     return decodeStream(stream);
57 }
58 
decodeMemory(const void * buffer,size_t size)59 bool SkAnimator::decodeMemory(const void* buffer, size_t size)
60 {
61     fMaker->fFileName.reset();
62     SkDisplayXMLParser parser(*fMaker);
63     return parser.parse((const char*)buffer, size);
64 }
65 
decodeStream(SkStream * stream)66 bool SkAnimator::decodeStream(SkStream* stream)
67 {
68     SkDisplayXMLParser parser(*fMaker);
69     bool result = parser.parse(*stream);
70     fMaker->setErrorString();
71     return result;
72 }
73 
decodeDOM(const SkDOM & dom,const SkDOMNode * node)74 bool SkAnimator::decodeDOM(const SkDOM& dom, const SkDOMNode* node)
75 {
76     fMaker->fFileName.reset();
77     SkDisplayXMLParser parser(*fMaker);
78     return parser.parse(dom, node);
79 }
80 
decodeURI(const char uri[])81 bool SkAnimator::decodeURI(const char uri[]) {
82 //  SkDebugf("animator decode %s\n", uri);
83 
84 //    SkStream* stream = SkStream::GetURIStream(fMaker->fPrefix.c_str(), uri);
85     SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(uri));
86     if (stream.get()) {
87         this->setURIBase(uri);
88         return decodeStream(stream);
89     } else {
90         return false;
91     }
92 }
93 
doCharEvent(SkUnichar code)94 bool SkAnimator::doCharEvent(SkUnichar code) {
95     if (code == 0)
96         return false;
97     struct SkEventState state;
98     state.fCode = code;
99     fMaker->fEnableTime = fMaker->getAppTime();
100     bool result = fMaker->fEvents.doEvent(*fMaker, SkDisplayEvent::kKeyChar, &state);
101     fMaker->notifyInval();
102     return result;
103 }
104 
doClickEvent(int clickState,SkScalar x,SkScalar y)105 bool SkAnimator::doClickEvent(int clickState, SkScalar x, SkScalar y) {
106     SkASSERT(clickState >= 0 && clickState <= 2);
107     struct SkEventState state;
108     state.fX = x;
109     state.fY = y;
110     fMaker->fEnableTime = fMaker->getAppTime();
111     bool result = fMaker->fEvents.doEvent(*fMaker,
112         clickState == 0 ? SkDisplayEvent::kMouseDown :
113         clickState == 1 ? SkDisplayEvent::kMouseDrag :
114         SkDisplayEvent::kMouseUp, &state);
115     fMaker->notifyInval();
116     return result;
117 }
118 
doKeyEvent(SkKey code)119 bool SkAnimator::doKeyEvent(SkKey code) {
120     if (code == 0)
121         return false;
122     struct SkEventState state;
123     state.fCode = code;
124     fMaker->fEnableTime = fMaker->getAppTime();
125     bool result = fMaker->fEvents.doEvent(*fMaker, SkDisplayEvent::kKeyPress, &state);
126     fMaker->notifyInval();
127     return result;
128 }
129 
doKeyUpEvent(SkKey code)130 bool SkAnimator::doKeyUpEvent(SkKey code) {
131     if (code == 0)
132         return false;
133     struct SkEventState state;
134     state.fCode = code;
135     fMaker->fEnableTime = fMaker->getAppTime();
136     bool result = fMaker->fEvents.doEvent(*fMaker, SkDisplayEvent::kKeyPressUp, &state);
137     fMaker->notifyInval();
138     return result;
139 }
140 
doUserEvent(const SkEvent & evt)141 bool SkAnimator::doUserEvent(const SkEvent& evt) {
142     fMaker->fEnableTime = fMaker->getAppTime();
143     return onEvent(evt);
144 }
145 
draw(SkCanvas * canvas,SkPaint * paint,SkMSec time)146 SkAnimator::DifferenceType SkAnimator::draw(SkCanvas* canvas, SkPaint* paint, SkMSec time) {
147     if (paint == nullptr)
148         return draw(canvas, time);
149     fMaker->fScreenplay.time = time;
150     fMaker->fCanvas = canvas;
151     fMaker->fPaint = paint;
152     fMaker->fDisplayList.fHasUnion = false;
153     int result = fMaker->fDisplayList.draw(*fMaker, time);
154     if (result)
155         result += fMaker->fDisplayList.fHasUnion;
156     return (DifferenceType) result;
157 }
158 
draw(SkCanvas * canvas,SkMSec time)159 SkAnimator::DifferenceType SkAnimator::draw(SkCanvas* canvas, SkMSec time) {
160     SkPaint paint;
161     return draw(canvas, &paint, time);
162 }
163 
164 #ifdef SK_DEBUG
eventDone(const SkEvent &)165 void SkAnimator::eventDone(const SkEvent& ) {
166 }
167 #endif
168 
findClickEvent(SkScalar x,SkScalar y)169 bool SkAnimator::findClickEvent(SkScalar x, SkScalar y) {
170     struct SkEventState state;
171     state.fDisable = true;
172     state.fX = x;
173     state.fY = y;
174     fMaker->fEnableTime = fMaker->getAppTime();
175     bool result = fMaker->fEvents.doEvent(*fMaker, SkDisplayEvent::kMouseDown, &state);
176     fMaker->notifyInval();
177     return result;
178 }
179 
getAnimator(const SkDisplayable * displayable) const180 const SkAnimator* SkAnimator::getAnimator(const SkDisplayable* displayable) const {
181     if (displayable->getType() != SkType_Movie)
182         return nullptr;
183     const SkDisplayMovie* movie = (const SkDisplayMovie*) displayable;
184     return movie->getAnimator();
185 }
186 
getElement(const char * id)187 const SkDisplayable* SkAnimator::getElement(const char* id) {
188     SkDisplayable* element;
189     if (fMaker->find(id, &element) == false)
190         return nullptr;
191     return (const SkDisplayable*) element;
192 }
193 
getElementType(const SkDisplayable * ae)194 SkElementType SkAnimator::getElementType(const SkDisplayable* ae) {
195     SkDisplayable* element = (SkDisplayable*) ae;
196     const SkMemberInfo* info = SkDisplayType::GetMembers(fMaker, element->getType(), nullptr);
197     return (SkElementType) SkDisplayType::Find(fMaker, info);
198 }
199 
getElementType(const char * id)200 SkElementType SkAnimator::getElementType(const char* id) {
201     const SkDisplayable* element = getElement(id);
202     return getElementType(element);
203 }
204 
getField(const SkDisplayable * ae,const char * field)205 const SkMemberInfo* SkAnimator::getField(const SkDisplayable* ae, const char* field) {
206     SkDisplayable* element = (SkDisplayable*) ae;
207     const SkMemberInfo* info = element->getMember(field);
208     return (const SkMemberInfo*) info;
209 }
210 
getField(const char * elementID,const char * field)211 const SkMemberInfo* SkAnimator::getField(const char* elementID, const char* field) {
212     const SkDisplayable* element = getElement(elementID);
213     return getField(element, field);
214 }
215 
getFieldType(const SkMemberInfo * ai)216 SkFieldType SkAnimator::getFieldType(const SkMemberInfo* ai) {
217     const SkMemberInfo* info = (const SkMemberInfo*) ai;
218     return (SkFieldType) info->getType();
219 }
220 
getFieldType(const char * id,const char * fieldID)221 SkFieldType SkAnimator::getFieldType(const char* id, const char* fieldID) {
222     const SkMemberInfo* field = getField(id, fieldID);
223     return getFieldType(field);
224 }
225 
getArrayCommon(const SkDisplayable * ae,const SkMemberInfo * ai,int index,SkOperand * operand)226 static bool getArrayCommon(const SkDisplayable* ae, const SkMemberInfo* ai,
227                            int index, SkOperand* operand) {
228     const SkDisplayable* element = (const SkDisplayable*) ae;
229     const SkMemberInfo* info = (const SkMemberInfo*) ai;
230     SkASSERT(info->fType == SkType_Array);
231     return info->getArrayValue(element, index, operand);
232 }
233 
getArrayInt(const SkDisplayable * ae,const SkMemberInfo * ai,int index)234 int32_t SkAnimator::getArrayInt(const SkDisplayable* ae,
235         const SkMemberInfo* ai, int index) {
236     SkOperand operand;
237     bool result = getArrayCommon(ae, ai, index, &operand);
238     return result ? operand.fS32 : SK_NaN32;
239 }
240 
getArrayInt(const char * id,const char * fieldID,int index)241 int32_t SkAnimator::getArrayInt(const char* id, const char* fieldID, int index) {
242     const SkDisplayable* element = getElement(id);
243     if (element == nullptr)
244         return SK_NaN32;
245     const SkMemberInfo* field = getField(element, fieldID);
246     if (field == nullptr)
247         return SK_NaN32;
248     return getArrayInt(element, field, index);
249 }
250 
getArrayScalar(const SkDisplayable * ae,const SkMemberInfo * ai,int index)251 SkScalar SkAnimator::getArrayScalar(const SkDisplayable* ae,
252         const SkMemberInfo* ai, int index) {
253     SkOperand operand;
254     bool result = getArrayCommon(ae, ai, index, &operand);
255     return result ? operand.fScalar : SK_ScalarNaN;
256 }
257 
getArrayScalar(const char * id,const char * fieldID,int index)258 SkScalar SkAnimator::getArrayScalar(const char* id, const char* fieldID, int index) {
259     const SkDisplayable* element = getElement(id);
260     if (element == nullptr)
261         return SK_ScalarNaN;
262     const SkMemberInfo* field = getField(element, fieldID);
263     if (field == nullptr)
264         return SK_ScalarNaN;
265     return getArrayScalar(element, field, index);
266 }
267 
getArrayString(const SkDisplayable * ae,const SkMemberInfo * ai,int index)268 const char* SkAnimator::getArrayString(const SkDisplayable* ae,
269         const SkMemberInfo* ai, int index) {
270     SkOperand operand;
271     bool result = getArrayCommon(ae, ai, index, &operand);
272     return result ? operand.fString->c_str() : nullptr;
273 }
274 
getArrayString(const char * id,const char * fieldID,int index)275 const char* SkAnimator::getArrayString(const char* id, const char* fieldID, int index) {
276     const SkDisplayable* element = getElement(id);
277     if (element == nullptr)
278         return nullptr;
279     const SkMemberInfo* field = getField(element, fieldID);
280     if (field == nullptr)
281         return nullptr;
282     return getArrayString(element, field, index);
283 }
284 
getInterval()285 SkMSec SkAnimator::getInterval() {
286     return fMaker->fMinimumInterval == (SkMSec) -1 ? 0 : fMaker->fMinimumInterval;
287 }
288 
getInvalBounds(SkRect * inval)289 void SkAnimator::getInvalBounds(SkRect* inval) {
290     if (fMaker->fDisplayList.fHasUnion) {
291         inval->fLeft = SkIntToScalar(fMaker->fDisplayList.fInvalBounds.fLeft);
292         inval->fTop = SkIntToScalar(fMaker->fDisplayList.fInvalBounds.fTop);
293         inval->fRight = SkIntToScalar(fMaker->fDisplayList.fInvalBounds.fRight);
294         inval->fBottom = SkIntToScalar(fMaker->fDisplayList.fInvalBounds.fBottom);
295     } else {
296         inval->fLeft = inval->fTop = -SK_ScalarMax;
297         inval->fRight = inval->fBottom = SK_ScalarMax;
298     }
299 }
300 
getParserError()301 const SkXMLParserError* SkAnimator::getParserError() {
302     return &fMaker->fError;
303 }
304 
getParserErrorString()305 const char* SkAnimator::getParserErrorString() {
306     if (fMaker->fErrorString.size() == 0 && fMaker->fError.hasError())
307         fMaker->setErrorString();
308     return fMaker->fErrorString.c_str();
309 }
310 
getInt(const SkDisplayable * element,const SkMemberInfo * info)311 int32_t SkAnimator::getInt(const SkDisplayable* element, const SkMemberInfo* info) {
312     if (info->fType != SkType_MemberProperty) {
313         SkOperand operand;
314         if (info->getType() == SkType_Int) {
315             info->getValue(element, &operand, 1);
316             return operand.fS32;
317         }
318         return SK_NaN32;
319     }
320     SkScriptValue scriptValue;
321     bool success = element->getProperty(info->propertyIndex(), &scriptValue);
322     if (success && scriptValue.fType == SkType_Int)
323         return scriptValue.fOperand.fS32;
324     return SK_NaN32;
325 }
326 
getInt(const char * id,const char * fieldID)327 int32_t SkAnimator::getInt(const char* id, const char* fieldID) {
328     const SkDisplayable* element = getElement(id);
329     if (element == nullptr)
330         return SK_NaN32;
331     const SkMemberInfo* field = getField(element, fieldID);
332     if (field == nullptr)
333         return SK_NaN32;
334     return getInt(element, field);
335 }
336 
getScalar(const SkDisplayable * element,const SkMemberInfo * info)337 SkScalar SkAnimator::getScalar(const SkDisplayable* element, const SkMemberInfo* info) {
338     if (info->fType != SkType_MemberProperty) {
339         SkOperand operand;
340         if (info->getType() == SkType_Float) {
341             info->getValue(element, &operand, 1);
342             return operand.fScalar;
343         }
344         return SK_ScalarNaN;
345     }
346     SkScriptValue scriptValue;
347     bool success = element->getProperty(info->propertyIndex(), &scriptValue);
348     if (success && scriptValue.fType == SkType_Float)
349         return scriptValue.fOperand.fScalar;
350     return SK_ScalarNaN;
351 }
352 
getScalar(const char * id,const char * fieldID)353 SkScalar SkAnimator::getScalar(const char* id, const char* fieldID) {
354     const SkDisplayable* element = getElement(id);
355     if (element == nullptr)
356         return SK_ScalarNaN;
357     const SkMemberInfo* field = getField(element, fieldID);
358     if (field == nullptr)
359         return SK_ScalarNaN;
360     return getScalar(element, field);
361 }
362 
getString(const SkDisplayable * ae,const SkMemberInfo * ai)363 const char* SkAnimator::getString(const SkDisplayable* ae,
364         const SkMemberInfo* ai) {
365     const SkDisplayable* element = (const SkDisplayable*) ae;
366     const SkMemberInfo* info = (const SkMemberInfo*) ai;
367     SkString* temp;
368     info->getString(element, &temp);
369     return temp->c_str();
370 }
371 
getString(const char * id,const char * fieldID)372 const char* SkAnimator::getString(const char* id, const char* fieldID) {
373     const SkDisplayable* element = getElement(id);
374     if (element == nullptr)
375         return nullptr;
376     const SkMemberInfo* field = getField(element, fieldID);
377     if (field == nullptr)
378         return nullptr;
379     return getString(element, field);
380 }
381 
getURIBase()382 const char* SkAnimator::getURIBase() {
383     return fMaker->fPrefix.c_str();
384 }
385 
initialize()386 void SkAnimator::initialize() {
387     delete fMaker;
388     fMaker = new SkAnimateMaker(this, nullptr, nullptr);
389     decodeMemory(gMathPrimer, sizeof(gMathPrimer)-1);
390 #ifdef SK_BUILD_FOR_ANDROID
391     InitializeSkExtraPathEffects(this);
392 #endif
393 }
394 
395 
396 #ifdef SK_DEBUG
isTrackingEvents()397 bool SkAnimator::isTrackingEvents() {
398     return false;
399 }
400 #endif
401 
onEvent(const SkEvent & evt)402 bool SkAnimator::onEvent(const SkEvent& evt) {
403 #ifdef SK_DEBUG
404     SkAnimator* root = fMaker->getRoot();
405     if (root == nullptr)
406         root = this;
407     if (root->isTrackingEvents())
408         root->eventDone(evt);
409 #endif
410     if (evt.isType(SK_EventType_OnEnd)) {
411         SkEventState eventState;
412         SkDEBUGCODE(bool success =) evt.findPtr("anim", (void**) &eventState.fDisplayable);
413         SkASSERT(success);
414         SkDEBUGCODE(success =) evt.findS32("time", (int32_t*) &fMaker->fEnableTime);
415         SkASSERT(success);
416         fMaker->fAdjustedStart = fMaker->getAppTime() - fMaker->fEnableTime;
417         fMaker->fEvents.doEvent(*fMaker, SkDisplayEvent::kOnEnd, &eventState);
418         fMaker->fAdjustedStart = 0;
419         goto inval;
420     }
421     if (evt.isType(SK_EventType_Delay)) {
422         fMaker->doDelayedEvent();
423         goto inval;
424     }
425     {
426         const char* id = evt.findString("id");
427         if (id == nullptr)
428             return false;
429         SkDisplayable** firstMovie = fMaker->fMovies.begin();
430         SkDisplayable** endMovie = fMaker->fMovies.end();
431         for (SkDisplayable** ptr = firstMovie; ptr < endMovie; ptr++) {
432             SkDisplayMovie* movie = (SkDisplayMovie*) *ptr;
433             movie->doEvent(evt);
434         }
435         {
436             SkDisplayable* event;
437             if (fMaker->find(id, &event) == false)
438                 return false;
439     #if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING
440             SkString debugOut;
441             SkMSec realTime = fMaker->getAppTime();
442             debugOut.appendS32(realTime - fMaker->fDebugTimeBase);
443             debugOut.append(" onEvent id=");
444             debugOut.append(id);
445     #endif
446             SkMSec time = evt.getFast32();
447             if (time != 0) {
448                 SkMSec app  = fMaker->getAppTime();
449                 fMaker->setEnableTime(app, time);
450     #if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING
451                 debugOut.append(" time=");
452                 debugOut.appendS32(time - fMaker->fDebugTimeBase);
453                 debugOut.append(" adjust=");
454                 debugOut.appendS32(fMaker->fAdjustedStart);
455     #endif
456             }
457     #if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING
458             SkDebugf("%s\n", debugOut.c_str());
459     #endif
460             SkASSERT(event->isEvent());
461             SkDisplayEvent* displayEvent = (SkDisplayEvent*) event;
462             displayEvent->populateInput(*fMaker, evt);
463             displayEvent->enableEvent(*fMaker);
464         }
465     }
466 inval:
467     fMaker->notifyInval();
468     return true;
469 }
470 
onEventPost(SkEvent * evt,SkEventSinkID sinkID)471 void SkAnimator::onEventPost(SkEvent* evt, SkEventSinkID sinkID)
472 {
473 #ifdef SK_DEBUG
474     SkAnimator* root = fMaker->getRoot();
475     if (root) {
476         root->onEventPost(evt, sinkID);
477         return;
478     }
479 #else
480     SkASSERT(sinkID == this->getSinkID() || this->getHostEventSinkID() == sinkID);
481 #endif
482     evt->setTargetID(sinkID)->post();
483 }
484 
onEventPostTime(SkEvent * evt,SkEventSinkID sinkID,SkMSec time)485 void SkAnimator::onEventPostTime(SkEvent* evt, SkEventSinkID sinkID, SkMSec time)
486 {
487 #ifdef SK_DEBUG
488     SkAnimator* root = fMaker->getRoot();
489     if (root) {
490         root->onEventPostTime(evt, sinkID, time);
491         return;
492     }
493 #else
494     SkASSERT(sinkID == this->getSinkID() || this->getHostEventSinkID() == sinkID);
495 #endif
496     evt->setTargetID(sinkID)->postTime(time);
497 }
498 
reset()499 void SkAnimator::reset() {
500     fMaker->fDisplayList.reset();
501 }
502 
getHostEventSinkID() const503 SkEventSinkID SkAnimator::getHostEventSinkID() const {
504     return fMaker->fHostEventSinkID;
505 }
506 
setHostEventSinkID(SkEventSinkID target)507 void SkAnimator::setHostEventSinkID(SkEventSinkID target) {
508     fMaker->fHostEventSinkID = target;
509 }
510 
onSetHostHandler(Handler)511 void SkAnimator::onSetHostHandler(Handler ) {
512 }
513 
setJavaOwner(Handler)514 void SkAnimator::setJavaOwner(Handler ) {
515 }
516 
setArrayString(const char * id,const char * fieldID,const char ** array,int num)517 bool SkAnimator::setArrayString(const char* id, const char* fieldID, const char** array, int num)
518 {
519     SkTypedArray tArray(SkType_String);
520     tArray.setCount(num);
521     for (int i = 0; i < num; i++) {
522         SkOperand op;
523         op.fString = new SkString(array[i]);
524         tArray[i] = op;
525     }
526     return setArray(id, fieldID, tArray);
527 }
setArrayInt(const char * id,const char * fieldID,const int * array,int num)528 bool SkAnimator::setArrayInt(const char* id, const char* fieldID, const int* array, int num)
529 {
530     SkTypedArray tArray(SkType_Int);
531     tArray.setCount(num);
532     for (int i = 0; i < num; i++) {
533         SkOperand op;
534         op.fS32 = array[i];
535         tArray[i] = op;
536     }
537     return setArray(id, fieldID, tArray);
538 }
539 
setArray(SkDisplayable * element,const SkMemberInfo * info,SkTypedArray array)540 bool SkAnimator::setArray(SkDisplayable* element, const SkMemberInfo* info, SkTypedArray array) {
541     if (info->fType != SkType_Array)
542         return false;   //the field is not an array
543     //i think we can handle the case where the displayable itself is an array differently from the
544     //case where it has an array - for one thing, if it is an array, i think we can change its type
545     //if it's not, we cannot
546     SkDisplayTypes type = element->getType();
547     if (type == SkType_Array) {
548         SkDisplayArray* dispArray = (SkDisplayArray*) element;
549         dispArray->values = array;
550         return true;
551     }
552     else
553         return false;   //currently i don't care about this case
554 }
555 
setArray(const char * id,const char * fieldID,SkTypedArray array)556 bool SkAnimator::setArray(const char* id, const char* fieldID, SkTypedArray array) {
557     SkDisplayable* element = (SkDisplayable*) getElement(id);
558     //should I go ahead and change all 'nullptr's to 'nullptr'?
559     if (element == nullptr)
560         return false;
561     const SkMemberInfo* field = getField(element, fieldID);
562     if (field == nullptr)
563         return false;
564     return setArray(element, field, array);
565 }
566 
setInt(SkDisplayable * element,const SkMemberInfo * info,int32_t s32)567 bool SkAnimator::setInt(SkDisplayable* element, const SkMemberInfo* info, int32_t s32) {
568     if (info->fType != SkType_MemberProperty) {
569         SkOperand operand;
570         operand.fS32 = s32;
571         SkASSERT(info->getType() == SkType_Int);
572         info->setValue(element, &operand, 1);
573     } else {
574         SkScriptValue scriptValue;
575         scriptValue.fType = SkType_Int;
576         scriptValue.fOperand.fS32 = s32;
577         element->setProperty(info->propertyIndex(), scriptValue);
578     }
579     return true;
580 }
581 
setInt(const char * id,const char * fieldID,int32_t s32)582 bool SkAnimator::setInt(const char* id, const char* fieldID, int32_t s32) {
583     SkDisplayable* element = (SkDisplayable*) getElement(id);
584     if (element == nullptr)
585         return false;
586     const SkMemberInfo* field = getField(element, fieldID);
587     if (field == nullptr)
588         return false;
589     return setInt(element, field, s32);
590 }
591 
setScalar(SkDisplayable * element,const SkMemberInfo * info,SkScalar scalar)592 bool SkAnimator::setScalar(SkDisplayable* element, const SkMemberInfo* info, SkScalar scalar) {
593     if (info->fType != SkType_MemberProperty) {
594         SkOperand operand;
595         operand.fScalar = scalar;
596         SkASSERT(info->getType() == SkType_Float);
597         info->setValue(element, &operand, 1);
598     } else {
599         SkScriptValue scriptValue;
600         scriptValue.fType = SkType_Float;
601         scriptValue.fOperand.fScalar = scalar;
602         element->setProperty(info->propertyIndex(), scriptValue);
603     }
604     return true;
605 }
606 
setScalar(const char * id,const char * fieldID,SkScalar scalar)607 bool SkAnimator::setScalar(const char* id, const char* fieldID, SkScalar scalar) {
608     SkDisplayable* element = (SkDisplayable*) getElement(id);
609     if (element == nullptr)
610         return false;
611     const SkMemberInfo* field = getField(element, fieldID);
612     if (field == nullptr)
613         return false;
614     return setScalar(element, field, scalar);
615 }
616 
setString(SkDisplayable * element,const SkMemberInfo * info,const char * str)617 bool SkAnimator::setString(SkDisplayable* element,
618         const SkMemberInfo* info, const char* str) {
619     // !!! until this is fixed, can't call script with global references from here
620     info->setValue(*fMaker, nullptr, 0, info->fCount, element, info->getType(), str, strlen(str));
621     return true;
622 }
623 
setString(const char * id,const char * fieldID,const char * str)624 bool SkAnimator::setString(const char* id, const char* fieldID, const char* str) {
625     SkDisplayable* element = (SkDisplayable*) getElement(id);
626     if (element == nullptr)
627         return false;
628     const SkMemberInfo* field = getField(element, fieldID);
629     if (field == nullptr)
630         return false;
631     return setString(element, field, str);
632 }
633 
setTimeline(const Timeline & timeline)634 void SkAnimator::setTimeline(const Timeline& timeline) {
635     fMaker->fTimeline = &timeline;
636 }
637 
setURIBase(const char * uri)638 void SkAnimator::setURIBase(const char* uri) {
639     if (uri)
640     {
641         const char* tail = strrchr(uri, '/');
642         if (tail) {
643             SkString prefix(uri, tail - uri + 1);
644             if (uri[0] != '.' /*SkStream::IsAbsoluteURI(uri)*/)
645                 fMaker->fPrefix.reset();
646             fMaker->fPrefix.append(prefix);
647             fMaker->fFileName.set(tail + 1);
648         } else
649             fMaker->fFileName.set(uri);
650     }
651 }
652 
653 #ifdef SK_DEBUG
NoLeaks()654 bool SkAnimator::NoLeaks() {
655 #ifdef SK_BUILD_FOR_MAC
656     if (SkDisplayable::fAllocations.count() == 0)
657         return true;
658 //  return SkDisplayable::fAllocationCount == 0;
659     SkDebugf("!!! leaked %d displayables:\n", SkDisplayable::fAllocations.count());
660     for (SkDisplayable** leak = SkDisplayable::fAllocations.begin(); leak < SkDisplayable::fAllocations.end(); leak++)
661         SkDebugf("%08x %s\n", *leak, (*leak)->id);
662 #endif
663     return false;
664 }
665 #endif
666 
667 #ifdef SK_SUPPORT_UNITTEST
668 #include "SkAnimatorScript.h"
669 #include "SkBase64.h"
670 #include "SkParse.h"
671 #include "SkMemberInfo.h"
672 
673 #define unittestline(type)  { #type , type::UnitTest }
674 #endif
675 
676 
677 #ifdef SK_SUPPORT_UNITTEST
Init(bool runUnitTests)678 void SkAnimator::Init(bool runUnitTests) {
679     if (runUnitTests == false)
680         return;
681     static const struct {
682         const char* fTypeName;
683         void (*fUnitTest)( );
684     } gUnitTests[] = {
685         unittestline(SkBase64),
686         unittestline(SkDisplayType),
687         unittestline(SkParse),
688         unittestline(SkScriptEngine),
689 //      unittestline(SkScriptEngine2),  // compiled script experiment
690         unittestline(SkAnimatorScript)
691     };
692     for (int i = 0; i < (int)SK_ARRAY_COUNT(gUnitTests); i++)
693     {
694         SkDebugf("SkAnimator: Running UnitTest for %s\n", gUnitTests[i].fTypeName);
695         gUnitTests[i].fUnitTest();
696         SkDebugf("SkAnimator: End UnitTest for %s\n", gUnitTests[i].fTypeName);
697     }
698 }
699 #else
Init(bool)700 void SkAnimator::Init(bool) {}
701 #endif
702 
Term()703 void SkAnimator::Term() {
704 }
705