1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/animator/SkDisplayXMLParser.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,316 @@ 1.4 + 1.5 +/* 1.6 + * Copyright 2006 The Android Open Source Project 1.7 + * 1.8 + * Use of this source code is governed by a BSD-style license that can be 1.9 + * found in the LICENSE file. 1.10 + */ 1.11 + 1.12 + 1.13 +#include "SkDisplayXMLParser.h" 1.14 +#include "SkAnimateMaker.h" 1.15 +#include "SkDisplayApply.h" 1.16 +#include "SkUtils.h" 1.17 +#ifdef SK_DEBUG 1.18 +#include "SkTime.h" 1.19 +#endif 1.20 + 1.21 +static char const* const gErrorStrings[] = { 1.22 + "unknown error ", 1.23 + "apply scopes itself", 1.24 + "display tree too deep (circular reference?) ", 1.25 + "element missing parent ", 1.26 + "element type not allowed in parent ", 1.27 + "error adding <data> to <post> ", 1.28 + "error adding to <matrix> ", 1.29 + "error adding to <paint> ", 1.30 + "error adding to <path> ", 1.31 + "error in attribute value ", 1.32 + "error in script ", 1.33 + "expected movie in sink attribute ", 1.34 + "field not in target ", 1.35 + "number of offsets in gradient must match number of colors", 1.36 + "no offset in gradient may be greater than one", 1.37 + "last offset in gradient must be one", 1.38 + "offsets in gradient must be increasing", 1.39 + "first offset in gradient must be zero", 1.40 + "gradient attribute \"points\" must have length of four", 1.41 + "in include ", 1.42 + "in movie ", 1.43 + "include name unknown or missing ", 1.44 + "index out of range ", 1.45 + "movie name unknown or missing ", 1.46 + "no parent available to resolve sink attribute ", 1.47 + "parent element can't contain ", 1.48 + "saveLayer must specify a bounds", 1.49 + "target id not found ", 1.50 + "unexpected type " 1.51 +}; 1.52 + 1.53 +SkDisplayXMLParserError::~SkDisplayXMLParserError() { 1.54 +} 1.55 + 1.56 +void SkDisplayXMLParserError::getErrorString(SkString* str) const { 1.57 + if (fCode > kUnknownError) 1.58 + str->set(gErrorStrings[fCode - kUnknownError]); 1.59 + else 1.60 + str->reset(); 1.61 + INHERITED::getErrorString(str); 1.62 +} 1.63 + 1.64 +void SkDisplayXMLParserError::setInnerError(SkAnimateMaker* parent, const SkString& src) { 1.65 + SkString inner; 1.66 + getErrorString(&inner); 1.67 + inner.prepend(": "); 1.68 + inner.prependS32(getLineNumber()); 1.69 + inner.prepend(", line "); 1.70 + inner.prepend(src); 1.71 + parent->setErrorNoun(inner); 1.72 +} 1.73 + 1.74 + 1.75 +SkDisplayXMLParser::SkDisplayXMLParser(SkAnimateMaker& maker) 1.76 + : INHERITED(&maker.fError), fMaker(maker), fInInclude(maker.fInInclude), 1.77 + fInSkia(maker.fInInclude), fCurrDisplayable(NULL) 1.78 +{ 1.79 +} 1.80 + 1.81 +SkDisplayXMLParser::~SkDisplayXMLParser() { 1.82 + if (fCurrDisplayable && fMaker.fChildren.find(fCurrDisplayable) < 0) 1.83 + delete fCurrDisplayable; 1.84 + for (Parent* parPtr = fParents.begin() + 1; parPtr < fParents.end(); parPtr++) { 1.85 + SkDisplayable* displayable = parPtr->fDisplayable; 1.86 + if (displayable == fCurrDisplayable) 1.87 + continue; 1.88 + SkASSERT(fMaker.fChildren.find(displayable) < 0); 1.89 + if (fMaker.fHelpers.find(displayable) < 0) 1.90 + delete displayable; 1.91 + } 1.92 +} 1.93 + 1.94 + 1.95 + 1.96 +bool SkDisplayXMLParser::onAddAttribute(const char name[], const char value[]) { 1.97 + return onAddAttributeLen(name, value, strlen(value)); 1.98 +} 1.99 + 1.100 +bool SkDisplayXMLParser::onAddAttributeLen(const char attrName[], const char attrValue[], 1.101 + size_t attrValueLen) 1.102 +{ 1.103 + if (fCurrDisplayable == NULL) // this signals we should ignore attributes for this element 1.104 + return strncmp(attrName, "xmlns", sizeof("xmlns") - 1) != 0; 1.105 + SkDisplayable* displayable = fCurrDisplayable; 1.106 + SkDisplayTypes type = fCurrType; 1.107 + 1.108 + if (strcmp(attrName, "id") == 0) { 1.109 + if (fMaker.find(attrValue, attrValueLen, NULL)) { 1.110 + fError->setNoun(attrValue, attrValueLen); 1.111 + fError->setCode(SkXMLParserError::kDuplicateIDs); 1.112 + return true; 1.113 + } 1.114 +#ifdef SK_DEBUG 1.115 + displayable->_id.set(attrValue, attrValueLen); 1.116 + displayable->id = displayable->_id.c_str(); 1.117 +#endif 1.118 + fMaker.idsSet(attrValue, attrValueLen, displayable); 1.119 + int parentIndex = fParents.count() - 1; 1.120 + if (parentIndex > 0) { 1.121 + SkDisplayable* parent = fParents[parentIndex - 1].fDisplayable; 1.122 + parent->setChildHasID(); 1.123 + } 1.124 + return false; 1.125 + } 1.126 + const char* name = attrName; 1.127 + const SkMemberInfo* info = SkDisplayType::GetMember(&fMaker, type, &name); 1.128 + if (info == NULL) { 1.129 + fError->setNoun(name); 1.130 + fError->setCode(SkXMLParserError::kUnknownAttributeName); 1.131 + return true; 1.132 + } 1.133 + if (info->setValue(fMaker, NULL, 0, info->getCount(), displayable, info->getType(), attrValue, 1.134 + attrValueLen)) 1.135 + return false; 1.136 + if (fMaker.fError.hasError()) { 1.137 + fError->setNoun(attrValue, attrValueLen); 1.138 + return true; 1.139 + } 1.140 + SkDisplayable* ref = NULL; 1.141 + if (fMaker.find(attrValue, attrValueLen, &ref) == false) { 1.142 + ref = fMaker.createInstance(attrValue, attrValueLen); 1.143 + if (ref == NULL) { 1.144 + fError->setNoun(attrValue, attrValueLen); 1.145 + fError->setCode(SkXMLParserError::kErrorInAttributeValue); 1.146 + return true; 1.147 + } else 1.148 + fMaker.helperAdd(ref); 1.149 + } 1.150 + if (info->fType != SkType_MemberProperty) { 1.151 + fError->setNoun(name); 1.152 + fError->setCode(SkXMLParserError::kUnknownAttributeName); 1.153 + return true; 1.154 + } 1.155 + SkScriptValue scriptValue; 1.156 + scriptValue.fOperand.fDisplayable = ref; 1.157 + scriptValue.fType = ref->getType(); 1.158 + displayable->setProperty(info->propertyIndex(), scriptValue); 1.159 + return false; 1.160 +} 1.161 + 1.162 +#if defined(SK_BUILD_FOR_WIN32) 1.163 + #define SK_strcasecmp _stricmp 1.164 + #define SK_strncasecmp _strnicmp 1.165 +#else 1.166 + #define SK_strcasecmp strcasecmp 1.167 + #define SK_strncasecmp strncasecmp 1.168 +#endif 1.169 + 1.170 +bool SkDisplayXMLParser::onEndElement(const char elem[]) 1.171 +{ 1.172 + int parentIndex = fParents.count() - 1; 1.173 + if (parentIndex >= 0) { 1.174 + Parent& container = fParents[parentIndex]; 1.175 + SkDisplayable* displayable = container.fDisplayable; 1.176 + fMaker.fEndDepth = parentIndex; 1.177 + displayable->onEndElement(fMaker); 1.178 + if (fMaker.fError.hasError()) 1.179 + return true; 1.180 + if (parentIndex > 0) { 1.181 + SkDisplayable* parent = fParents[parentIndex - 1].fDisplayable; 1.182 + bool result = parent->addChild(fMaker, displayable); 1.183 + if (fMaker.hasError()) 1.184 + return true; 1.185 + if (result == false) { 1.186 + int infoCount; 1.187 + const SkMemberInfo* info = 1.188 + SkDisplayType::GetMembers(&fMaker, fParents[parentIndex - 1].fType, &infoCount); 1.189 + const SkMemberInfo* foundInfo; 1.190 + if ((foundInfo = searchContainer(info, infoCount)) != NULL) { 1.191 + parent->setReference(foundInfo, displayable); 1.192 + // if (displayable->isHelper() == false) 1.193 + fMaker.helperAdd(displayable); 1.194 + } else { 1.195 + fMaker.setErrorCode(SkDisplayXMLParserError::kElementTypeNotAllowedInParent); 1.196 + return true; 1.197 + } 1.198 + } 1.199 + if (parent->childrenNeedDisposing()) 1.200 + delete displayable; 1.201 + } 1.202 + fParents.remove(parentIndex); 1.203 + } 1.204 + fCurrDisplayable = NULL; 1.205 + if (fInInclude == false && SK_strcasecmp(elem, "screenplay") == 0) { 1.206 + if (fMaker.fInMovie == false) { 1.207 + fMaker.fEnableTime = fMaker.getAppTime(); 1.208 +#if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING 1.209 + if (fMaker.fDebugTimeBase == (SkMSec) -1) 1.210 + fMaker.fDebugTimeBase = fMaker.fEnableTime; 1.211 + SkString debugOut; 1.212 + SkMSec time = fMaker.getAppTime(); 1.213 + debugOut.appendS32(time - fMaker.fDebugTimeBase); 1.214 + debugOut.append(" onLoad enable="); 1.215 + debugOut.appendS32(fMaker.fEnableTime - fMaker.fDebugTimeBase); 1.216 + SkDebugf("%s\n", debugOut.c_str()); 1.217 +#endif 1.218 + fMaker.fEvents.doEvent(fMaker, SkDisplayEvent::kOnload, NULL); 1.219 + if (fMaker.fError.hasError()) 1.220 + return true; 1.221 + fMaker.fEvents.removeEvent(SkDisplayEvent::kOnload, NULL); 1.222 + 1.223 + } 1.224 + fInSkia = false; 1.225 + } 1.226 + return false; 1.227 +} 1.228 + 1.229 +bool SkDisplayXMLParser::onStartElement(const char name[]) 1.230 +{ 1.231 + return onStartElementLen(name, strlen(name)); 1.232 +} 1.233 + 1.234 +bool SkDisplayXMLParser::onStartElementLen(const char name[], size_t len) { 1.235 + fCurrDisplayable = NULL; // init so we'll ignore attributes if we exit early 1.236 + 1.237 + if (SK_strncasecmp(name, "screenplay", len) == 0) { 1.238 + fInSkia = true; 1.239 + if (fInInclude == false) 1.240 + fMaker.idsSet(name, len, &fMaker.fScreenplay); 1.241 + return false; 1.242 + } 1.243 + if (fInSkia == false) 1.244 + return false; 1.245 + 1.246 + SkDisplayable* displayable = fMaker.createInstance(name, len); 1.247 + if (displayable == NULL) { 1.248 + fError->setNoun(name, len); 1.249 + fError->setCode(SkXMLParserError::kUnknownElement); 1.250 + return true; 1.251 + } 1.252 + SkDisplayTypes type = displayable->getType(); 1.253 + Parent record = { displayable, type }; 1.254 + *fParents.append() = record; 1.255 + if (fParents.count() == 1) 1.256 + fMaker.childrenAdd(displayable); 1.257 + else { 1.258 + Parent* parent = fParents.end() - 2; 1.259 + if (displayable->setParent(parent->fDisplayable)) { 1.260 + fError->setNoun(name, len); 1.261 + getError()->setCode(SkDisplayXMLParserError::kParentElementCantContain); 1.262 + return true; 1.263 + } 1.264 + } 1.265 + 1.266 + // set these for subsequent calls to addAttribute() 1.267 + fCurrDisplayable = displayable; 1.268 + fCurrType = type; 1.269 + return false; 1.270 +} 1.271 + 1.272 +const SkMemberInfo* SkDisplayXMLParser::searchContainer(const SkMemberInfo* infoBase, 1.273 + int infoCount) { 1.274 + const SkMemberInfo* bestDisplayable = NULL; 1.275 + const SkMemberInfo* lastResort = NULL; 1.276 + for (int index = 0; index < infoCount; index++) { 1.277 + const SkMemberInfo* info = &infoBase[index]; 1.278 + if (info->fType == SkType_BaseClassInfo) { 1.279 + const SkMemberInfo* inherited = info->getInherited(); 1.280 + const SkMemberInfo* result = searchContainer(inherited, info->fCount); 1.281 + if (result != NULL) 1.282 + return result; 1.283 + continue; 1.284 + } 1.285 + Parent* container = fParents.end() - 1; 1.286 + SkDisplayTypes type = (SkDisplayTypes) info->fType; 1.287 + if (type == SkType_MemberProperty) 1.288 + type = info->propertyType(); 1.289 + SkDisplayTypes containerType = container->fType; 1.290 + if (type == containerType && (type == SkType_Rect || type == SkType_Polygon || 1.291 + type == SkType_Array || type == SkType_Int || type == SkType_Bitmap)) 1.292 + goto rectNext; 1.293 + while (type != containerType) { 1.294 + if (containerType == SkType_Displayable) 1.295 + goto next; 1.296 + containerType = SkDisplayType::GetParent(&fMaker, containerType); 1.297 + if (containerType == SkType_Unknown) 1.298 + goto next; 1.299 + } 1.300 + return info; 1.301 +next: 1.302 + if (type == SkType_Drawable || (type == SkType_Displayable && 1.303 + container->fDisplayable->isDrawable())) { 1.304 +rectNext: 1.305 + if (fParents.count() > 1) { 1.306 + Parent* parent = fParents.end() - 2; 1.307 + if (info == parent->fDisplayable->preferredChild(type)) 1.308 + bestDisplayable = info; 1.309 + else 1.310 + lastResort = info; 1.311 + } 1.312 + } 1.313 + } 1.314 + if (bestDisplayable) 1.315 + return bestDisplayable; 1.316 + if (lastResort) 1.317 + return lastResort; 1.318 + return NULL; 1.319 +}