gfx/skia/trunk/src/animator/SkDisplayXMLParser.cpp

Thu, 15 Jan 2015 15:55:04 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:55:04 +0100
branch
TOR_BUG_9701
changeset 9
a63d609f5ebe
permissions
-rw-r--r--

Back out 97036ab72558 which inappropriately compared turds to third parties.

michael@0 1
michael@0 2 /*
michael@0 3 * Copyright 2006 The Android Open Source Project
michael@0 4 *
michael@0 5 * Use of this source code is governed by a BSD-style license that can be
michael@0 6 * found in the LICENSE file.
michael@0 7 */
michael@0 8
michael@0 9
michael@0 10 #include "SkDisplayXMLParser.h"
michael@0 11 #include "SkAnimateMaker.h"
michael@0 12 #include "SkDisplayApply.h"
michael@0 13 #include "SkUtils.h"
michael@0 14 #ifdef SK_DEBUG
michael@0 15 #include "SkTime.h"
michael@0 16 #endif
michael@0 17
michael@0 18 static char const* const gErrorStrings[] = {
michael@0 19 "unknown error ",
michael@0 20 "apply scopes itself",
michael@0 21 "display tree too deep (circular reference?) ",
michael@0 22 "element missing parent ",
michael@0 23 "element type not allowed in parent ",
michael@0 24 "error adding <data> to <post> ",
michael@0 25 "error adding to <matrix> ",
michael@0 26 "error adding to <paint> ",
michael@0 27 "error adding to <path> ",
michael@0 28 "error in attribute value ",
michael@0 29 "error in script ",
michael@0 30 "expected movie in sink attribute ",
michael@0 31 "field not in target ",
michael@0 32 "number of offsets in gradient must match number of colors",
michael@0 33 "no offset in gradient may be greater than one",
michael@0 34 "last offset in gradient must be one",
michael@0 35 "offsets in gradient must be increasing",
michael@0 36 "first offset in gradient must be zero",
michael@0 37 "gradient attribute \"points\" must have length of four",
michael@0 38 "in include ",
michael@0 39 "in movie ",
michael@0 40 "include name unknown or missing ",
michael@0 41 "index out of range ",
michael@0 42 "movie name unknown or missing ",
michael@0 43 "no parent available to resolve sink attribute ",
michael@0 44 "parent element can't contain ",
michael@0 45 "saveLayer must specify a bounds",
michael@0 46 "target id not found ",
michael@0 47 "unexpected type "
michael@0 48 };
michael@0 49
michael@0 50 SkDisplayXMLParserError::~SkDisplayXMLParserError() {
michael@0 51 }
michael@0 52
michael@0 53 void SkDisplayXMLParserError::getErrorString(SkString* str) const {
michael@0 54 if (fCode > kUnknownError)
michael@0 55 str->set(gErrorStrings[fCode - kUnknownError]);
michael@0 56 else
michael@0 57 str->reset();
michael@0 58 INHERITED::getErrorString(str);
michael@0 59 }
michael@0 60
michael@0 61 void SkDisplayXMLParserError::setInnerError(SkAnimateMaker* parent, const SkString& src) {
michael@0 62 SkString inner;
michael@0 63 getErrorString(&inner);
michael@0 64 inner.prepend(": ");
michael@0 65 inner.prependS32(getLineNumber());
michael@0 66 inner.prepend(", line ");
michael@0 67 inner.prepend(src);
michael@0 68 parent->setErrorNoun(inner);
michael@0 69 }
michael@0 70
michael@0 71
michael@0 72 SkDisplayXMLParser::SkDisplayXMLParser(SkAnimateMaker& maker)
michael@0 73 : INHERITED(&maker.fError), fMaker(maker), fInInclude(maker.fInInclude),
michael@0 74 fInSkia(maker.fInInclude), fCurrDisplayable(NULL)
michael@0 75 {
michael@0 76 }
michael@0 77
michael@0 78 SkDisplayXMLParser::~SkDisplayXMLParser() {
michael@0 79 if (fCurrDisplayable && fMaker.fChildren.find(fCurrDisplayable) < 0)
michael@0 80 delete fCurrDisplayable;
michael@0 81 for (Parent* parPtr = fParents.begin() + 1; parPtr < fParents.end(); parPtr++) {
michael@0 82 SkDisplayable* displayable = parPtr->fDisplayable;
michael@0 83 if (displayable == fCurrDisplayable)
michael@0 84 continue;
michael@0 85 SkASSERT(fMaker.fChildren.find(displayable) < 0);
michael@0 86 if (fMaker.fHelpers.find(displayable) < 0)
michael@0 87 delete displayable;
michael@0 88 }
michael@0 89 }
michael@0 90
michael@0 91
michael@0 92
michael@0 93 bool SkDisplayXMLParser::onAddAttribute(const char name[], const char value[]) {
michael@0 94 return onAddAttributeLen(name, value, strlen(value));
michael@0 95 }
michael@0 96
michael@0 97 bool SkDisplayXMLParser::onAddAttributeLen(const char attrName[], const char attrValue[],
michael@0 98 size_t attrValueLen)
michael@0 99 {
michael@0 100 if (fCurrDisplayable == NULL) // this signals we should ignore attributes for this element
michael@0 101 return strncmp(attrName, "xmlns", sizeof("xmlns") - 1) != 0;
michael@0 102 SkDisplayable* displayable = fCurrDisplayable;
michael@0 103 SkDisplayTypes type = fCurrType;
michael@0 104
michael@0 105 if (strcmp(attrName, "id") == 0) {
michael@0 106 if (fMaker.find(attrValue, attrValueLen, NULL)) {
michael@0 107 fError->setNoun(attrValue, attrValueLen);
michael@0 108 fError->setCode(SkXMLParserError::kDuplicateIDs);
michael@0 109 return true;
michael@0 110 }
michael@0 111 #ifdef SK_DEBUG
michael@0 112 displayable->_id.set(attrValue, attrValueLen);
michael@0 113 displayable->id = displayable->_id.c_str();
michael@0 114 #endif
michael@0 115 fMaker.idsSet(attrValue, attrValueLen, displayable);
michael@0 116 int parentIndex = fParents.count() - 1;
michael@0 117 if (parentIndex > 0) {
michael@0 118 SkDisplayable* parent = fParents[parentIndex - 1].fDisplayable;
michael@0 119 parent->setChildHasID();
michael@0 120 }
michael@0 121 return false;
michael@0 122 }
michael@0 123 const char* name = attrName;
michael@0 124 const SkMemberInfo* info = SkDisplayType::GetMember(&fMaker, type, &name);
michael@0 125 if (info == NULL) {
michael@0 126 fError->setNoun(name);
michael@0 127 fError->setCode(SkXMLParserError::kUnknownAttributeName);
michael@0 128 return true;
michael@0 129 }
michael@0 130 if (info->setValue(fMaker, NULL, 0, info->getCount(), displayable, info->getType(), attrValue,
michael@0 131 attrValueLen))
michael@0 132 return false;
michael@0 133 if (fMaker.fError.hasError()) {
michael@0 134 fError->setNoun(attrValue, attrValueLen);
michael@0 135 return true;
michael@0 136 }
michael@0 137 SkDisplayable* ref = NULL;
michael@0 138 if (fMaker.find(attrValue, attrValueLen, &ref) == false) {
michael@0 139 ref = fMaker.createInstance(attrValue, attrValueLen);
michael@0 140 if (ref == NULL) {
michael@0 141 fError->setNoun(attrValue, attrValueLen);
michael@0 142 fError->setCode(SkXMLParserError::kErrorInAttributeValue);
michael@0 143 return true;
michael@0 144 } else
michael@0 145 fMaker.helperAdd(ref);
michael@0 146 }
michael@0 147 if (info->fType != SkType_MemberProperty) {
michael@0 148 fError->setNoun(name);
michael@0 149 fError->setCode(SkXMLParserError::kUnknownAttributeName);
michael@0 150 return true;
michael@0 151 }
michael@0 152 SkScriptValue scriptValue;
michael@0 153 scriptValue.fOperand.fDisplayable = ref;
michael@0 154 scriptValue.fType = ref->getType();
michael@0 155 displayable->setProperty(info->propertyIndex(), scriptValue);
michael@0 156 return false;
michael@0 157 }
michael@0 158
michael@0 159 #if defined(SK_BUILD_FOR_WIN32)
michael@0 160 #define SK_strcasecmp _stricmp
michael@0 161 #define SK_strncasecmp _strnicmp
michael@0 162 #else
michael@0 163 #define SK_strcasecmp strcasecmp
michael@0 164 #define SK_strncasecmp strncasecmp
michael@0 165 #endif
michael@0 166
michael@0 167 bool SkDisplayXMLParser::onEndElement(const char elem[])
michael@0 168 {
michael@0 169 int parentIndex = fParents.count() - 1;
michael@0 170 if (parentIndex >= 0) {
michael@0 171 Parent& container = fParents[parentIndex];
michael@0 172 SkDisplayable* displayable = container.fDisplayable;
michael@0 173 fMaker.fEndDepth = parentIndex;
michael@0 174 displayable->onEndElement(fMaker);
michael@0 175 if (fMaker.fError.hasError())
michael@0 176 return true;
michael@0 177 if (parentIndex > 0) {
michael@0 178 SkDisplayable* parent = fParents[parentIndex - 1].fDisplayable;
michael@0 179 bool result = parent->addChild(fMaker, displayable);
michael@0 180 if (fMaker.hasError())
michael@0 181 return true;
michael@0 182 if (result == false) {
michael@0 183 int infoCount;
michael@0 184 const SkMemberInfo* info =
michael@0 185 SkDisplayType::GetMembers(&fMaker, fParents[parentIndex - 1].fType, &infoCount);
michael@0 186 const SkMemberInfo* foundInfo;
michael@0 187 if ((foundInfo = searchContainer(info, infoCount)) != NULL) {
michael@0 188 parent->setReference(foundInfo, displayable);
michael@0 189 // if (displayable->isHelper() == false)
michael@0 190 fMaker.helperAdd(displayable);
michael@0 191 } else {
michael@0 192 fMaker.setErrorCode(SkDisplayXMLParserError::kElementTypeNotAllowedInParent);
michael@0 193 return true;
michael@0 194 }
michael@0 195 }
michael@0 196 if (parent->childrenNeedDisposing())
michael@0 197 delete displayable;
michael@0 198 }
michael@0 199 fParents.remove(parentIndex);
michael@0 200 }
michael@0 201 fCurrDisplayable = NULL;
michael@0 202 if (fInInclude == false && SK_strcasecmp(elem, "screenplay") == 0) {
michael@0 203 if (fMaker.fInMovie == false) {
michael@0 204 fMaker.fEnableTime = fMaker.getAppTime();
michael@0 205 #if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING
michael@0 206 if (fMaker.fDebugTimeBase == (SkMSec) -1)
michael@0 207 fMaker.fDebugTimeBase = fMaker.fEnableTime;
michael@0 208 SkString debugOut;
michael@0 209 SkMSec time = fMaker.getAppTime();
michael@0 210 debugOut.appendS32(time - fMaker.fDebugTimeBase);
michael@0 211 debugOut.append(" onLoad enable=");
michael@0 212 debugOut.appendS32(fMaker.fEnableTime - fMaker.fDebugTimeBase);
michael@0 213 SkDebugf("%s\n", debugOut.c_str());
michael@0 214 #endif
michael@0 215 fMaker.fEvents.doEvent(fMaker, SkDisplayEvent::kOnload, NULL);
michael@0 216 if (fMaker.fError.hasError())
michael@0 217 return true;
michael@0 218 fMaker.fEvents.removeEvent(SkDisplayEvent::kOnload, NULL);
michael@0 219
michael@0 220 }
michael@0 221 fInSkia = false;
michael@0 222 }
michael@0 223 return false;
michael@0 224 }
michael@0 225
michael@0 226 bool SkDisplayXMLParser::onStartElement(const char name[])
michael@0 227 {
michael@0 228 return onStartElementLen(name, strlen(name));
michael@0 229 }
michael@0 230
michael@0 231 bool SkDisplayXMLParser::onStartElementLen(const char name[], size_t len) {
michael@0 232 fCurrDisplayable = NULL; // init so we'll ignore attributes if we exit early
michael@0 233
michael@0 234 if (SK_strncasecmp(name, "screenplay", len) == 0) {
michael@0 235 fInSkia = true;
michael@0 236 if (fInInclude == false)
michael@0 237 fMaker.idsSet(name, len, &fMaker.fScreenplay);
michael@0 238 return false;
michael@0 239 }
michael@0 240 if (fInSkia == false)
michael@0 241 return false;
michael@0 242
michael@0 243 SkDisplayable* displayable = fMaker.createInstance(name, len);
michael@0 244 if (displayable == NULL) {
michael@0 245 fError->setNoun(name, len);
michael@0 246 fError->setCode(SkXMLParserError::kUnknownElement);
michael@0 247 return true;
michael@0 248 }
michael@0 249 SkDisplayTypes type = displayable->getType();
michael@0 250 Parent record = { displayable, type };
michael@0 251 *fParents.append() = record;
michael@0 252 if (fParents.count() == 1)
michael@0 253 fMaker.childrenAdd(displayable);
michael@0 254 else {
michael@0 255 Parent* parent = fParents.end() - 2;
michael@0 256 if (displayable->setParent(parent->fDisplayable)) {
michael@0 257 fError->setNoun(name, len);
michael@0 258 getError()->setCode(SkDisplayXMLParserError::kParentElementCantContain);
michael@0 259 return true;
michael@0 260 }
michael@0 261 }
michael@0 262
michael@0 263 // set these for subsequent calls to addAttribute()
michael@0 264 fCurrDisplayable = displayable;
michael@0 265 fCurrType = type;
michael@0 266 return false;
michael@0 267 }
michael@0 268
michael@0 269 const SkMemberInfo* SkDisplayXMLParser::searchContainer(const SkMemberInfo* infoBase,
michael@0 270 int infoCount) {
michael@0 271 const SkMemberInfo* bestDisplayable = NULL;
michael@0 272 const SkMemberInfo* lastResort = NULL;
michael@0 273 for (int index = 0; index < infoCount; index++) {
michael@0 274 const SkMemberInfo* info = &infoBase[index];
michael@0 275 if (info->fType == SkType_BaseClassInfo) {
michael@0 276 const SkMemberInfo* inherited = info->getInherited();
michael@0 277 const SkMemberInfo* result = searchContainer(inherited, info->fCount);
michael@0 278 if (result != NULL)
michael@0 279 return result;
michael@0 280 continue;
michael@0 281 }
michael@0 282 Parent* container = fParents.end() - 1;
michael@0 283 SkDisplayTypes type = (SkDisplayTypes) info->fType;
michael@0 284 if (type == SkType_MemberProperty)
michael@0 285 type = info->propertyType();
michael@0 286 SkDisplayTypes containerType = container->fType;
michael@0 287 if (type == containerType && (type == SkType_Rect || type == SkType_Polygon ||
michael@0 288 type == SkType_Array || type == SkType_Int || type == SkType_Bitmap))
michael@0 289 goto rectNext;
michael@0 290 while (type != containerType) {
michael@0 291 if (containerType == SkType_Displayable)
michael@0 292 goto next;
michael@0 293 containerType = SkDisplayType::GetParent(&fMaker, containerType);
michael@0 294 if (containerType == SkType_Unknown)
michael@0 295 goto next;
michael@0 296 }
michael@0 297 return info;
michael@0 298 next:
michael@0 299 if (type == SkType_Drawable || (type == SkType_Displayable &&
michael@0 300 container->fDisplayable->isDrawable())) {
michael@0 301 rectNext:
michael@0 302 if (fParents.count() > 1) {
michael@0 303 Parent* parent = fParents.end() - 2;
michael@0 304 if (info == parent->fDisplayable->preferredChild(type))
michael@0 305 bestDisplayable = info;
michael@0 306 else
michael@0 307 lastResort = info;
michael@0 308 }
michael@0 309 }
michael@0 310 }
michael@0 311 if (bestDisplayable)
michael@0 312 return bestDisplayable;
michael@0 313 if (lastResort)
michael@0 314 return lastResort;
michael@0 315 return NULL;
michael@0 316 }

mercurial