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.

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

mercurial