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