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