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