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 "SkDisplayEvent.h"
11 #include "SkAnimateMaker.h"
12 #include "SkDisplayApply.h"
13 #include "SkDisplayInput.h"
14 #include "SkDisplayList.h"
15 #ifdef SK_DEBUG
16 #include "SkDump.h"
17 #endif
18 #include "SkEvent.h"
19 #include "SkDisplayInput.h"
20 #include "SkKey.h"
21 #include "SkMetaData.h"
22 #include "SkScript.h"
23 #include "SkUtils.h"
24 
25 enum SkDisplayEvent_Properties {
26     SK_PROPERTY(key),
27     SK_PROPERTY(keys)
28 };
29 
30 #if SK_USE_CONDENSED_INFO == 0
31 
32 const SkMemberInfo SkDisplayEvent::fInfo[] = {
33     SK_MEMBER(code, EventCode),
34     SK_MEMBER(disable, Boolean),
35     SK_MEMBER_PROPERTY(key, String), // a single key (also last key pressed)
36     SK_MEMBER_PROPERTY(keys, String), // a single key or dash-delimited range of keys
37     SK_MEMBER(kind, EventKind),
38     SK_MEMBER(target, String),
39     SK_MEMBER(x, Float),
40     SK_MEMBER(y, Float)
41 };
42 
43 #endif
44 
45 DEFINE_GET_MEMBER(SkDisplayEvent);
46 
SkDisplayEvent()47 SkDisplayEvent::SkDisplayEvent() : code((SkKey) -1), disable(false),
48     kind(kUser), x(0), y(0), fLastCode((SkKey) -1), fMax((SkKey) -1), fTarget(nullptr) {
49 }
50 
~SkDisplayEvent()51 SkDisplayEvent::~SkDisplayEvent() {
52     deleteMembers();
53 }
54 
addChild(SkAnimateMaker &,SkDisplayable * child)55 bool SkDisplayEvent::addChild(SkAnimateMaker& , SkDisplayable* child) {
56     *fChildren.append() = child;
57     return true;
58 }
59 
contains(SkDisplayable * match)60 bool SkDisplayEvent::contains(SkDisplayable* match) {
61     for (int index = 0; index < fChildren.count(); index++) {
62         if (fChildren[index] == match || fChildren[index]->contains(match))
63             return true;
64     }
65     return false;
66 }
67 
contains(const SkString & match)68 SkDisplayable* SkDisplayEvent::contains(const SkString& match) {
69     for (int index = 0; index < fChildren.count(); index++) {
70         SkDisplayable* child = fChildren[index];
71         if (child->contains(match))
72             return child;
73     }
74     return nullptr;
75 }
76 
deleteMembers()77 void SkDisplayEvent::deleteMembers() {
78     for (int index = 0; index < fChildren.count(); index++) {
79         SkDisplayable* evt = fChildren[index];
80         delete evt;
81     }
82 }
83 
84 #ifdef SK_DUMP_ENABLED
dumpEvent(SkAnimateMaker * maker)85 void SkDisplayEvent::dumpEvent(SkAnimateMaker* maker) {
86     dumpBase(maker);
87     SkString str;
88     SkDump::GetEnumString(SkType_EventKind, kind, &str);
89     SkDebugf("kind=\"%s\" ", str.c_str());
90     if (kind == SkDisplayEvent::kKeyPress || kind == SkDisplayEvent::kKeyPressUp) {
91         if (code >= 0)
92             SkDump::GetEnumString(SkType_EventCode, code, &str);
93         else
94             str.set("none");
95         SkDebugf("code=\"%s\" ", str.c_str());
96     }
97     if (kind == SkDisplayEvent::kKeyChar) {
98         if (fMax != (SkKey) -1 && fMax != code)
99             SkDebugf("keys=\"%c - %c\" ", code, fMax);
100         else
101             SkDebugf("key=\"%c\" ", code);
102     }
103     if (fTarget != nullptr) {
104         SkDebugf("target=\"%s\" ", fTarget->id);
105     }
106     if (kind >= SkDisplayEvent::kMouseDown && kind <= SkDisplayEvent::kMouseUp) {
107         SkDebugf("x=\"%g\" y=\"%g\" ", SkScalarToFloat(x), SkScalarToFloat(y));
108     }
109     if (disable)
110         SkDebugf("disable=\"true\" ");
111     SkDebugf("/>\n");
112 }
113 #endif
114 
enableEvent(SkAnimateMaker & maker)115 bool SkDisplayEvent::enableEvent(SkAnimateMaker& maker)
116 {
117     maker.fActiveEvent = this;
118     if (fChildren.count() == 0)
119         return false;
120     if (disable)
121         return false;
122 #ifdef SK_DUMP_ENABLED
123     if (maker.fDumpEvents) {
124         SkDebugf("enable: ");
125         dumpEvent(&maker);
126     }
127 #endif
128     SkDisplayList& displayList = maker.fDisplayList;
129     for (int index = 0; index < fChildren.count(); index++) {
130         SkDisplayable* displayable = fChildren[index];
131         if (displayable->isGroup()) {
132             SkTDDrawableArray* parentList = displayList.getDrawList();
133             *parentList->append() = (SkADrawable*) displayable;  // make it findable before children are enabled
134         }
135         if (displayable->enable(maker))
136             continue;
137         if (maker.hasError())
138             return true;
139         if (displayable->isDrawable() == false)
140             return true;    // error
141         SkADrawable* drawable = (SkADrawable*) displayable;
142         SkTDDrawableArray* parentList = displayList.getDrawList();
143         *parentList->append() = drawable;
144     }
145     return false;
146 }
147 
getProperty(int index,SkScriptValue * value) const148 bool SkDisplayEvent::getProperty(int index, SkScriptValue* value) const {
149     switch (index) {
150         case SK_PROPERTY(key):
151         case SK_PROPERTY(keys): {
152             value->fType = SkType_String;
153             char scratch[8];
154             SkKey convert = index == SK_PROPERTY(keys) ? code : fLastCode;
155             size_t size = convert > 0 ? SkUTF8_FromUnichar(convert, scratch) : 0;
156             fKeyString.set(scratch, size);
157             value->fOperand.fString = &fKeyString;
158             if (index != SK_PROPERTY(keys) || fMax == (SkKey) -1 || fMax == code)
159                 break;
160             value->fOperand.fString->append("-");
161             size = SkUTF8_FromUnichar(fMax, scratch);
162             value->fOperand.fString->append(scratch, size);
163             } break;
164         default:
165             SkASSERT(0);
166             return false;
167     }
168     return true;
169 }
170 
onEndElement(SkAnimateMaker & maker)171 void SkDisplayEvent::onEndElement(SkAnimateMaker& maker)
172 {
173     if (kind == kUser)
174         return;
175     maker.fEvents.addEvent(this);
176     if (kind == kOnEnd) {
177         SkDEBUGCODE(bool found = ) maker.find(target.c_str(), &fTarget);
178         SkASSERT(found);
179         SkASSERT(fTarget && fTarget->isAnimate());
180         SkAnimateBase* animate = (SkAnimateBase*) fTarget;
181         animate->setHasEndEvent();
182     }
183 }
184 
populateInput(SkAnimateMaker & maker,const SkEvent & fEvent)185 void SkDisplayEvent::populateInput(SkAnimateMaker& maker, const SkEvent& fEvent) {
186     const SkMetaData& meta = fEvent.getMetaData();
187     SkMetaData::Iter iter(meta);
188     SkMetaData::Type    type;
189     int number;
190     const char* name;
191     while ((name = iter.next(&type, &number)) != nullptr) {
192         if (name[0] == '\0')
193             continue;
194         SkDisplayable* displayable;
195         SkInput* input;
196         for (int index = 0; index < fChildren.count(); index++) {
197             displayable = fChildren[index];
198             if (displayable->getType() != SkType_Input)
199                 continue;
200             input = (SkInput*) displayable;
201             if (input->name.equals(name))
202                 goto found;
203         }
204         if (!maker.find(name, &displayable) || displayable->getType() != SkType_Input)
205             continue;
206         input = (SkInput*) displayable;
207     found:
208         switch (type) {
209             case SkMetaData::kS32_Type:
210                 meta.findS32(name, &input->fInt);
211                 break;
212             case SkMetaData::kScalar_Type:
213                 meta.findScalar(name, &input->fFloat);
214                 break;
215             case SkMetaData::kPtr_Type:
216                 SkASSERT(0);
217                 break; // !!! not handled for now
218             case SkMetaData::kString_Type:
219                 input->string.set(meta.findString(name));
220                 break;
221             default:
222                 SkASSERT(0);
223         }
224     }
225     // re-evaluate all animators that may have built their values from input strings
226     for (SkDisplayable** childPtr = fChildren.begin(); childPtr < fChildren.end(); childPtr++) {
227         SkDisplayable* displayable = *childPtr;
228         if (displayable->isApply() == false)
229             continue;
230         SkApply* apply = (SkApply*) displayable;
231         apply->refresh(maker);
232     }
233 }
234 
setProperty(int index,SkScriptValue & value)235 bool SkDisplayEvent::setProperty(int index, SkScriptValue& value) {
236     SkASSERT(index == SK_PROPERTY(key) || index == SK_PROPERTY(keys));
237     SkASSERT(value.fType == SkType_String);
238     SkString* string = value.fOperand.fString;
239     const char* chars = string->c_str();
240     int count = SkUTF8_CountUnichars(chars);
241     SkASSERT(count >= 1);
242     code = (SkKey) SkUTF8_NextUnichar(&chars);
243     fMax = code;
244     SkASSERT(count == 1 || index == SK_PROPERTY(keys));
245     if (--count > 0) {
246         SkASSERT(*chars == '-');
247         chars++;
248         fMax = (SkKey) SkUTF8_NextUnichar(&chars);
249         SkASSERT(fMax >= code);
250     }
251     return true;
252 }
253