blob: cc45b216ba5ddf9e950c74b6931e8a019345eaaf [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
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
reed@android.com8a1c16f2008-12-17 15:59:43 +00009
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
21enum SkPost_Properties {
22 SK_PROPERTY(target),
23 SK_PROPERTY(type)
24};
25
26#if SK_USE_CONDENSED_INFO == 0
27
28const 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
39DEFINE_GET_MEMBER(SkPost);
40
41SkPost::SkPost() : delay(0), /*initialized(SkBool(-1)), */ mode(kImmediate), fMaker(NULL),
42 fSinkID(0), fTargetMaker(NULL), fChildHasID(false), fDirty(false) {
43}
44
45SkPost::~SkPost() {
reed@google.com8d0b5772011-06-24 13:07:31 +000046 for (SkDataInput** part = fParts.begin(); part < fParts.end(); part++)
reed@android.com8a1c16f2008-12-17 15:59:43 +000047 delete *part;
48}
49
tfarina@chromium.org1d3c4112012-12-03 14:38:08 +000050bool SkPost::addChild(SkAnimateMaker& , SkDisplayable* child) {
reed@google.com8d0b5772011-06-24 13:07:31 +000051 SkASSERT(child && child->isDataInput());
52 SkDataInput* part = (SkDataInput*) child;
reed@android.com8a1c16f2008-12-17 15:59:43 +000053 *fParts.append() = part;
54 return true;
55}
56
rmistry@google.comd6176b02012-08-23 18:14:13 +000057bool SkPost::childrenNeedDisposing() const {
58 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +000059}
60
rmistry@google.comd6176b02012-08-23 18:14:13 +000061void SkPost::dirty() {
62 fDirty = true;
reed@android.com8a1c16f2008-12-17 15:59:43 +000063}
64
65#ifdef SK_DUMP_ENABLED
66void 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;
rmistry@google.comd6176b02012-08-23 18:14:13 +000077
reed@android.com8a1c16f2008-12-17 15:59:43 +000078 if (delay > 0) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000079 SkDebugf("delay=\"%g\" ", SkScalarToFloat(SkScalarDiv(delay, 1000)));
reed@android.com8a1c16f2008-12-17 15:59:43 +000080 }
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
rmistry@google.comd6176b02012-08-23 18:14:13 +0000102 //and the parts seem to be in the reverse order from the one in which we find the
reed@android.com8a1c16f2008-12-17 15:59:43 +0000103 //data itself
reed@google.com8d0b5772011-06-24 13:07:31 +0000104 //SkDataInput** ptr = fParts.end();
105 //SkDataInput* data;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000106 //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);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000130 SkDebugf("float=\"%g\" ", SkScalarToFloat(scalar));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000131 } 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
166bool 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);
reed@google.com8d0b5772011-06-24 13:07:31 +0000177 for (SkDataInput** part = fParts.begin(); part < fParts.end(); part++) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000178 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;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000214 if (isAnimatorEvent)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000215 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
232void 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, '.');
humper@google.com0e515772013-01-07 19:54:40 +0000238 size_t len = end ? (size_t) (end - ch) : strlen(ch);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000239 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}
rmistry@google.comd6176b02012-08-23 18:14:13 +0000263
reed@android.com8a1c16f2008-12-17 15:59:43 +0000264bool SkPost::hasEnable() const {
265 return true;
266}
267
268void SkPost::onEndElement(SkAnimateMaker& maker) {
269 fTargetMaker = fMaker = &maker;
270 if (fChildHasID == false) {
reed@google.com8d0b5772011-06-24 13:07:31 +0000271 for (SkDataInput** part = fParts.begin(); part < fParts.end(); part++)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000272 delete *part;
273 fParts.reset();
274 }
275}
276
rmistry@google.comd6176b02012-08-23 18:14:13 +0000277void SkPost::setChildHasID() {
278 fChildHasID = true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000279}
280
281bool 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}