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