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 45 SkAnimator::SkAnimator() : fMaker(NULL) { 46 initialize(); 47 } 48 49 SkAnimator::~SkAnimator() { 50 SkDELETE(fMaker); 51 } 52 53 void SkAnimator::addExtras(SkExtras* extras) { 54 *fMaker->fExtras.append() = extras; 55 } 56 57 bool SkAnimator::appendStream(SkStream* stream) { 58 return decodeStream(stream); 59 } 60 61 bool 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 68 bool SkAnimator::decodeStream(SkStream* stream) 69 { 70 SkDisplayXMLParser parser(*fMaker); 71 bool result = parser.parse(*stream); 72 fMaker->setErrorString(); 73 return result; 74 } 75 76 bool 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 83 bool SkAnimator::decodeURI(const char uri[]) { 84 // SkDebugf("animator decode %s\n", uri); 85 86 // SkStream* stream = SkStream::GetURIStream(fMaker->fPrefix.c_str(), uri); 87 SkAutoTUnref<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 96 bool 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 107 bool 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 121 bool 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 132 bool 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 143 bool SkAnimator::doUserEvent(const SkEvent& evt) { 144 fMaker->fEnableTime = fMaker->getAppTime(); 145 return onEvent(evt); 146 } 147 148 SkAnimator::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 161 SkAnimator::DifferenceType SkAnimator::draw(SkCanvas* canvas, SkMSec time) { 162 SkPaint paint; 163 return draw(canvas, &paint, time); 164 } 165 166 #ifdef SK_DEBUG 167 void SkAnimator::eventDone(const SkEvent& ) { 168 } 169 #endif 170 171 bool 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 182 const 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 189 const 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 196 SkElementType 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 202 SkElementType SkAnimator::getElementType(const char* id) { 203 const SkDisplayable* element = getElement(id); 204 return getElementType(element); 205 } 206 207 const 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 213 const SkMemberInfo* SkAnimator::getField(const char* elementID, const char* field) { 214 const SkDisplayable* element = getElement(elementID); 215 return getField(element, field); 216 } 217 218 SkFieldType SkAnimator::getFieldType(const SkMemberInfo* ai) { 219 const SkMemberInfo* info = (const SkMemberInfo*) ai; 220 return (SkFieldType) info->getType(); 221 } 222 223 SkFieldType SkAnimator::getFieldType(const char* id, const char* fieldID) { 224 const SkMemberInfo* field = getField(id, fieldID); 225 return getFieldType(field); 226 } 227 228 static 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 236 int32_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 243 int32_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 253 SkScalar 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 260 SkScalar 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 270 const 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 277 const 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 287 SkMSec SkAnimator::getInterval() { 288 return fMaker->fMinimumInterval == (SkMSec) -1 ? 0 : fMaker->fMinimumInterval; 289 } 290 291 void 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 303 const SkXMLParserError* SkAnimator::getParserError() { 304 return &fMaker->fError; 305 } 306 307 const char* SkAnimator::getParserErrorString() { 308 if (fMaker->fErrorString.size() == 0 && fMaker->fError.hasError()) 309 fMaker->setErrorString(); 310 return fMaker->fErrorString.c_str(); 311 } 312 313 int32_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 329 int32_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 339 SkScalar 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 355 SkScalar 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 365 const 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 374 const 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 384 const char* SkAnimator::getURIBase() { 385 return fMaker->fPrefix.c_str(); 386 } 387 388 void 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 399 bool SkAnimator::isTrackingEvents() { 400 return false; 401 } 402 #endif 403 404 bool 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 } 468 inval: 469 fMaker->notifyInval(); 470 return true; 471 } 472 473 void 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 487 void 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 501 void SkAnimator::reset() { 502 fMaker->fDisplayList.reset(); 503 } 504 505 SkEventSinkID SkAnimator::getHostEventSinkID() const { 506 return fMaker->fHostEventSinkID; 507 } 508 509 void SkAnimator::setHostEventSinkID(SkEventSinkID target) { 510 fMaker->fHostEventSinkID = target; 511 } 512 513 void SkAnimator::onSetHostHandler(Handler ) { 514 } 515 516 void SkAnimator::setJavaOwner(Handler ) { 517 } 518 519 bool 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 } 530 bool 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 542 bool 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 558 bool 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 569 bool 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 584 bool 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 594 bool 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 609 bool 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 619 bool 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 626 bool 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 636 void SkAnimator::setTimeline(const Timeline& timeline) { 637 fMaker->fTimeline = &timeline; 638 } 639 640 void 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 656 bool 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 680 void 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 702 void SkAnimator::Init(bool) {} 703 #endif 704 705 void SkAnimator::Term() { 706 } 707