blob: 242398bba8fed1afd8424d0e8314e30bd4c1bb4f [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001/* 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
64SkAnimator::SkAnimator() : fMaker(NULL) {
65 initialize();
66}
67
68SkAnimator::~SkAnimator() {
69 SkDELETE(fMaker);
70}
71
72void SkAnimator::addExtras(SkExtras* extras) {
73 *fMaker->fExtras.append() = extras;
74}
75
76bool SkAnimator::appendStream(SkStream* stream) {
77 return decodeStream(stream);
78}
79
80bool 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
87bool SkAnimator::decodeStream(SkStream* stream)
88{
89 SkDisplayXMLParser parser(*fMaker);
90 bool result = parser.parse(*stream);
91 fMaker->setErrorString();
92 return result;
93}
94
95bool 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
102bool 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
113bool 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
124bool 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
138bool 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
149bool 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
160bool SkAnimator::doUserEvent(const SkEvent& evt) {
161 fMaker->fEnableTime = fMaker->getAppTime();
162 return onEvent(evt);
163}
164
165SkAnimator::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
178SkAnimator::DifferenceType SkAnimator::draw(SkCanvas* canvas, SkMSec time) {
179 SkPaint paint;
180 return draw(canvas, &paint, time);
181}
182
183#ifdef SK_DEBUG
184void SkAnimator::eventDone(const SkEvent& ) {
185}
186#endif
187
188bool 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
199const 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
206const 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
213SkElementType 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
219SkElementType SkAnimator::getElementType(const char* id) {
220 const SkDisplayable* element = getElement(id);
221 return getElementType(element);
222}
223
224const 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
230const SkMemberInfo* SkAnimator::getField(const char* elementID, const char* field) {
231 const SkDisplayable* element = getElement(elementID);
232 return getField(element, field);
233}
234
235SkFieldType SkAnimator::getFieldType(const SkMemberInfo* ai) {
236 const SkMemberInfo* info = (const SkMemberInfo*) ai;
237 return (SkFieldType) info->getType();
238}
239
240SkFieldType SkAnimator::getFieldType(const char* id, const char* fieldID) {
241 const SkMemberInfo* field = getField(id, fieldID);
242 return getFieldType(field);
243}
244
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
253int32_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
260int32_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
270SkScalar 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
277SkScalar 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
287const 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
294const 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
304SkMSec SkAnimator::getInterval() {
305 return fMaker->fMinimumInterval == (SkMSec) -1 ? 0 : fMaker->fMinimumInterval;
306}
307
308void 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
320const SkXMLParserError* SkAnimator::getParserError() {
321 return &fMaker->fError;
322}
323
324const char* SkAnimator::getParserErrorString() {
325 if (fMaker->fErrorString.size() == 0 && fMaker->fError.hasError())
326 fMaker->setErrorString();
327 return fMaker->fErrorString.c_str();
328}
329
330int32_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
346int32_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
356SkScalar 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
372SkScalar 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
382const 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
391const 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
401const char* SkAnimator::getURIBase() {
402 return fMaker->fPrefix.c_str();
403}
404
405void 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
416bool SkAnimator::isTrackingEvents() {
417 return false;
418}
419#endif
420
421bool 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 }
485inval:
486 fMaker->notifyInval();
487 return true;
488}
489
490void 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
504void 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
518void SkAnimator::reset() {
519 fMaker->fDisplayList.reset();
520}
521
522SkEventSinkID SkAnimator::getHostEventSinkID() const {
523 return fMaker->fHostEventSinkID;
524}
525
526void SkAnimator::setHostEventSinkID(SkEventSinkID target) {
527 fMaker->fHostEventSinkID = target;
528}
529
530void SkAnimator::onSetHostHandler(Handler ) {
531}
532
533void SkAnimator::setJavaOwner(Handler ) {
534}
535
536bool 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}
547bool 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
559bool 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
575bool 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
586bool 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
601bool 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
611bool 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
626bool 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
636bool 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
643bool 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
653void SkAnimator::setTimeline(const Timeline& timeline) {
654 fMaker->fTimeline = &timeline;
655}
656
657void 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
673bool 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
696void 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
720void SkAnimator::Term() {
721}
722
723
724