Home | History | Annotate | Download | only in animator
      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 "SkDisplayPost.h"
     11 #include "SkAnimateMaker.h"
     12 #include "SkAnimator.h"
     13 #include "SkDisplayMovie.h"
     14 #include "SkPostParts.h"
     15 #include "SkScript.h"
     16 #ifdef SK_DEBUG
     17 #include "SkDump.h"
     18 #include "SkTime.h"
     19 #endif
     20 
     21 enum SkPost_Properties {
     22     SK_PROPERTY(target),
     23     SK_PROPERTY(type)
     24 };
     25 
     26 #if SK_USE_CONDENSED_INFO == 0
     27 
     28 const SkMemberInfo SkPost::fInfo[] = {
     29     SK_MEMBER(delay, MSec),
     30 //  SK_MEMBER(initialized, Boolean),
     31     SK_MEMBER(mode, EventMode),
     32     SK_MEMBER(sink, String),
     33     SK_MEMBER_PROPERTY(target, String),
     34     SK_MEMBER_PROPERTY(type, String)
     35 };
     36 
     37 #endif
     38 
     39 DEFINE_GET_MEMBER(SkPost);
     40 
     41 SkPost::SkPost() : delay(0), /*initialized(SkBool(-1)), */ mode(kImmediate), fMaker(NULL),
     42     fSinkID(0), fTargetMaker(NULL), fChildHasID(false), fDirty(false) {
     43 }
     44 
     45 SkPost::~SkPost() {
     46     for (SkDataInput** part = fParts.begin(); part < fParts.end();  part++)
     47         delete *part;
     48 }
     49 
     50 bool SkPost::addChild(SkAnimateMaker& , SkDisplayable* child) {
     51     SkASSERT(child && child->isDataInput());
     52     SkDataInput* part = (SkDataInput*) child;
     53     *fParts.append() = part;
     54     return true;
     55 }
     56 
     57 bool SkPost::childrenNeedDisposing() const {
     58     return false;
     59 }
     60 
     61 void SkPost::dirty() {
     62     fDirty = true;
     63 }
     64 
     65 #ifdef SK_DUMP_ENABLED
     66 void SkPost::dump(SkAnimateMaker* maker) {
     67     dumpBase(maker);
     68     SkString* eventType = new SkString();
     69     fEvent.getType(eventType);
     70     if (eventType->equals("user")) {
     71         const char* target = fEvent.findString("id");
     72         SkDebugf("target=\"%s\" ", target);
     73     }
     74     else
     75         SkDebugf("type=\"%s\" ", eventType->c_str());
     76     delete eventType;
     77 
     78     if (delay > 0) {
     79         SkDebugf("delay=\"%g\" ", SkScalarToFloat(SkScalarDiv(delay, 1000)));
     80     }
     81 //  if (initialized == false)
     82 //      SkDebugf("(uninitialized) ");
     83     SkString string;
     84     SkDump::GetEnumString(SkType_EventMode, mode, &string);
     85     if (!string.equals("immediate"))
     86         SkDebugf("mode=\"%s\" ", string.c_str());
     87     // !!! could enhance this to search through make hierarchy to show name of sink
     88     if (sink.size() > 0) {
     89         SkDebugf("sink=\"%s\" sinkID=\"%d\" ", sink.c_str(), fSinkID);
     90     } else if (fSinkID != maker->getAnimator()->getSinkID() && fSinkID != 0) {
     91         SkDebugf("sinkID=\"%d\" ", fSinkID);
     92     }
     93     const SkMetaData& meta = fEvent.getMetaData();
     94     SkMetaData::Iter iter(meta);
     95     SkMetaData::Type    type;
     96     int number;
     97     const char* name;
     98     bool closedYet = false;
     99     SkDisplayList::fIndent += 4;
    100     //this seems to work, but kinda hacky
    101     //for some reason the last part is id, which i don't want
    102     //and the parts seem to be in the reverse order from the one in which we find the
    103     //data itself
    104     //SkDataInput** ptr = fParts.end();
    105     //SkDataInput* data;
    106     //const char* ID;
    107     while ((name = iter.next(&type, &number)) != NULL) {
    108         //ptr--;
    109         if (strcmp(name, "id") == 0)
    110             continue;
    111         if (closedYet == false) {
    112             SkDebugf(">\n");
    113             closedYet = true;
    114         }
    115         //data = *ptr;
    116         //if (data->id)
    117         //    ID = data->id;
    118         //else
    119         //    ID = "";
    120         SkDebugf("%*s<data name=\"%s\" ", SkDisplayList::fIndent, "", name);
    121         switch (type) {
    122             case SkMetaData::kS32_Type: {
    123                 int32_t s32;
    124                 meta.findS32(name, &s32);
    125                 SkDebugf("int=\"%d\" ", s32);
    126                 } break;
    127             case SkMetaData::kScalar_Type: {
    128                 SkScalar scalar;
    129                 meta.findScalar(name, &scalar);
    130                 SkDebugf("float=\"%g\" ", SkScalarToFloat(scalar));
    131                 } break;
    132             case SkMetaData::kString_Type:
    133                 SkDebugf("string=\"%s\" ", meta.findString(name));
    134                 break;
    135             case SkMetaData::kPtr_Type: {//when do we have a pointer
    136                     void* ptr;
    137                     meta.findPtr(name, &ptr);
    138                     SkDebugf("0x%08x ", ptr);
    139                 } break;
    140             case SkMetaData::kBool_Type: {
    141                 bool boolean;
    142                 meta.findBool(name, &boolean);
    143                 SkDebugf("boolean=\"%s\" ", boolean ? "true " : "false ");
    144                 } break;
    145             default:
    146                 break;
    147         }
    148         SkDebugf("/>\n");
    149         //ptr++;
    150 /*      perhaps this should only be done in the case of a pointer?
    151         SkDisplayable* displayable;
    152         if (maker->find(name, &displayable))
    153             displayable->dump(maker);
    154         else
    155             SkDebugf("\n");*/
    156     }
    157     SkDisplayList::fIndent -= 4;
    158     if (closedYet)
    159         dumpEnd(maker);
    160     else
    161         SkDebugf("/>\n");
    162 
    163 }
    164 #endif
    165 
    166 bool SkPost::enable(SkAnimateMaker& maker ) {
    167     if (maker.hasError())
    168         return true;
    169     if (fDirty) {
    170         if (sink.size() > 0)
    171             findSinkID();
    172         if (fChildHasID) {
    173             SkString preserveID(fEvent.findString("id"));
    174             fEvent.getMetaData().reset();
    175             if (preserveID.size() > 0)
    176                 fEvent.setString("id", preserveID);
    177             for (SkDataInput** part = fParts.begin(); part < fParts.end();  part++) {
    178                 if ((*part)->add())
    179                     maker.setErrorCode(SkDisplayXMLParserError::kErrorAddingDataToPost);
    180             }
    181         }
    182         fDirty = false;
    183     }
    184 #ifdef SK_DUMP_ENABLED
    185     if (maker.fDumpPosts) {
    186         SkDebugf("post enable: ");
    187         dump(&maker);
    188     }
    189 #if defined SK_DEBUG_ANIMATION_TIMING
    190     SkString debugOut;
    191     SkMSec time = maker.getAppTime();
    192     debugOut.appendS32(time - maker.fDebugTimeBase);
    193     debugOut.append(" post id=");
    194     debugOut.append(_id);
    195     debugOut.append(" enable=");
    196     debugOut.appendS32(maker.fEnableTime - maker.fDebugTimeBase);
    197     debugOut.append(" delay=");
    198     debugOut.appendS32(delay);
    199 #endif
    200 #endif
    201 //  SkMSec adjustedDelay = maker.adjustDelay(maker.fEnableTime, delay);
    202     SkMSec futureTime = maker.fEnableTime + delay;
    203     fEvent.setFast32(futureTime);
    204 #if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING
    205     debugOut.append(" future=");
    206     debugOut.appendS32(futureTime - maker.fDebugTimeBase);
    207     SkDebugf("%s\n", debugOut.c_str());
    208 #endif
    209     SkEventSinkID targetID = fSinkID;
    210     bool isAnimatorEvent = true;
    211     SkAnimator* anim = maker.getAnimator();
    212     if (targetID == 0) {
    213         isAnimatorEvent = fEvent.findString("id") != NULL;
    214         if (isAnimatorEvent)
    215             targetID = anim->getSinkID();
    216         else if (maker.fHostEventSinkID)
    217             targetID = maker.fHostEventSinkID;
    218         else
    219             return true;
    220     } else
    221         anim = fTargetMaker->getAnimator();
    222     if (delay == 0) {
    223         if (isAnimatorEvent && mode == kImmediate)
    224             fTargetMaker->doEvent(fEvent);
    225         else
    226             anim->onEventPost(new SkEvent(fEvent), targetID);
    227     } else
    228         anim->onEventPostTime(new SkEvent(fEvent), targetID, futureTime);
    229     return true;
    230 }
    231 
    232 void SkPost::findSinkID() {
    233     // get the next delimiter '.' if any
    234     fTargetMaker = fMaker;
    235     const char* ch = sink.c_str();
    236     do {
    237         const char* end = strchr(ch, '.');
    238         size_t len = end ? (size_t) (end - ch) : strlen(ch);
    239         SkDisplayable* displayable = NULL;
    240         if (SK_LITERAL_STR_EQUAL("parent", ch, len)) {
    241             if (fTargetMaker->fParentMaker)
    242                 fTargetMaker = fTargetMaker->fParentMaker;
    243             else {
    244                 fTargetMaker->setErrorCode(SkDisplayXMLParserError::kNoParentAvailable);
    245                 return;
    246             }
    247         } else {
    248             fTargetMaker->find(ch, len, &displayable);
    249             if (displayable == NULL || displayable->getType() != SkType_Movie) {
    250                 fTargetMaker->setErrorCode(SkDisplayXMLParserError::kExpectedMovie);
    251                 return;
    252             }
    253             SkDisplayMovie* movie = (SkDisplayMovie*) displayable;
    254             fTargetMaker = movie->fMovie.fMaker;
    255         }
    256         if (end == NULL)
    257             break;
    258         ch = ++end;
    259     } while (true);
    260     SkAnimator* anim = fTargetMaker->getAnimator();
    261     fSinkID = anim->getSinkID();
    262 }
    263 
    264 bool SkPost::hasEnable() const {
    265     return true;
    266 }
    267 
    268 void SkPost::onEndElement(SkAnimateMaker& maker) {
    269     fTargetMaker = fMaker = &maker;
    270     if (fChildHasID == false) {
    271         for (SkDataInput** part = fParts.begin(); part < fParts.end();  part++)
    272             delete *part;
    273         fParts.reset();
    274     }
    275 }
    276 
    277 void SkPost::setChildHasID() {
    278     fChildHasID = true;
    279 }
    280 
    281 bool SkPost::setProperty(int index, SkScriptValue& value) {
    282     SkASSERT(value.fType == SkType_String);
    283     SkString* string = value.fOperand.fString;
    284     switch(index) {
    285         case SK_PROPERTY(target): {
    286             fEvent.setType("user");
    287             fEvent.setString("id", *string);
    288             mode = kImmediate;
    289             } break;
    290         case SK_PROPERTY(type):
    291             fEvent.setType(*string);
    292             break;
    293         default:
    294             SkASSERT(0);
    295             return false;
    296     }
    297     return true;
    298 }
    299