• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
SkPost()41 SkPost::SkPost() : delay(0), /*initialized(SkBool(-1)), */ mode(kImmediate), fMaker(NULL),
42     fSinkID(0), fTargetMaker(NULL), fChildHasID(false), fDirty(false) {
43 }
44 
~SkPost()45 SkPost::~SkPost() {
46     for (SkDataInput** part = fParts.begin(); part < fParts.end();  part++)
47         delete *part;
48 }
49 
add(SkAnimateMaker &,SkDisplayable * child)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 
childrenNeedDisposing() const57 bool SkPost::childrenNeedDisposing() const {
58     return false;
59 }
60 
dirty()61 void SkPost::dirty() {
62     fDirty = true;
63 }
64 
65 #ifdef SK_DUMP_ENABLED
dump(SkAnimateMaker * maker)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 
enable(SkAnimateMaker & maker)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 
findSinkID()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 
hasEnable() const272 bool SkPost::hasEnable() const {
273     return true;
274 }
275 
onEndElement(SkAnimateMaker & maker)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 
setChildHasID()285 void SkPost::setChildHasID() {
286     fChildHasID = true;
287 }
288 
setProperty(int index,SkScriptValue & value)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