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

changeset 0
6474c204b198
     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 +}

mercurial