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