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