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 25enum SkDisplayEvent_Properties { 26 SK_PROPERTY(key), 27 SK_PROPERTY(keys) 28}; 29 30#if SK_USE_CONDENSED_INFO == 0 31 32const 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 45DEFINE_GET_MEMBER(SkDisplayEvent); 46 47SkDisplayEvent::SkDisplayEvent() : code((SkKey) -1), disable(false), 48 kind(kUser), x(0), y(0), fLastCode((SkKey) -1), fMax((SkKey) -1), fTarget(nullptr) { 49} 50 51SkDisplayEvent::~SkDisplayEvent() { 52 deleteMembers(); 53} 54 55bool SkDisplayEvent::addChild(SkAnimateMaker& , SkDisplayable* child) { 56 *fChildren.append() = child; 57 return true; 58} 59 60bool 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 68SkDisplayable* 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 77void 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 85void 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 115bool 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 148bool 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 171void 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 185void 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 235bool 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