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