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 53 SkAnimator::SkAnimator() : fMaker(NULL) { 54 initialize(); 55 } 56 57 SkAnimator::~SkAnimator() { 58 SkDELETE(fMaker); 59 } 60 61 void SkAnimator::addExtras(SkExtras* extras) { 62 *fMaker->fExtras.append() = extras; 63 } 64 65 bool SkAnimator::appendStream(SkStream* stream) { 66 return decodeStream(stream); 67 } 68 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 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 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 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 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 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 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 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 149 bool SkAnimator::doUserEvent(const SkEvent& evt) { 150 fMaker->fEnableTime = fMaker->getAppTime(); 151 return onEvent(evt); 152 } 153 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 167 SkAnimator::DifferenceType SkAnimator::draw(SkCanvas* canvas, SkMSec time) { 168 SkPaint paint; 169 return draw(canvas, &paint, time); 170 } 171 172 #ifdef SK_DEBUG 173 void SkAnimator::eventDone(const SkEvent& ) { 174 } 175 #endif 176 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 188 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 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 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 208 SkElementType SkAnimator::getElementType(const char* id) { 209 const SkDisplayable* element = getElement(id); 210 return getElementType(element); 211 } 212 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 219 const SkMemberInfo* SkAnimator::getField(const char* elementID, const char* field) { 220 const SkDisplayable* element = getElement(elementID); 221 return getField(element, field); 222 } 223 224 SkFieldType SkAnimator::getFieldType(const SkMemberInfo* ai) { 225 const SkMemberInfo* info = (const SkMemberInfo*) ai; 226 return (SkFieldType) info->getType(); 227 } 228 229 SkFieldType SkAnimator::getFieldType(const char* id, const char* fieldID) { 230 const SkMemberInfo* field = getField(id, fieldID); 231 return getFieldType(field); 232 } 233 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 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 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 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 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 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 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 293 SkMSec SkAnimator::getInterval() { 294 return fMaker->fMinimumInterval == (SkMSec) -1 ? 0 : fMaker->fMinimumInterval; 295 } 296 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 309 const SkXMLParserError* SkAnimator::getParserError() { 310 return &fMaker->fError; 311 } 312 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 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 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 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 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 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 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 390 const char* SkAnimator::getURIBase() { 391 return fMaker->fPrefix.c_str(); 392 } 393 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 405 bool SkAnimator::isTrackingEvents() { 406 return false; 407 } 408 #endif 409 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 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 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 507 void SkAnimator::reset() { 508 fMaker->fDisplayList.reset(); 509 } 510 511 SkEventSinkID SkAnimator::getHostEventSinkID() const { 512 return fMaker->fHostEventSinkID; 513 } 514 515 void SkAnimator::setHostEventSinkID(SkEventSinkID target) { 516 fMaker->fHostEventSinkID = target; 517 } 518 519 void SkAnimator::onSetHostHandler(Handler ) { 520 } 521 522 void SkAnimator::setJavaOwner(Handler ) { 523 } 524 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 } 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 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 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 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 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 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 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 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 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 642 void SkAnimator::setTimeline(const Timeline& timeline) { 643 fMaker->fTimeline = &timeline; 644 } 645 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 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 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 709 void SkAnimator::Term() { 710 } 711 712 713 714