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