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

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/skia/trunk/src/animator/SkAnimatorScript2.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,622 @@
     1.4 +
     1.5 +/*
     1.6 + * Copyright 2011 Google Inc.
     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 +#include "SkAnimatorScript2.h"
    1.12 +#include "SkAnimateBase.h"
    1.13 +#include "SkAnimateMaker.h"
    1.14 +#include "SkDisplayTypes.h"
    1.15 +#include "SkExtras.h"
    1.16 +#include "SkMemberInfo.h"
    1.17 +#include "SkOpArray.h"
    1.18 +#include "SkParse.h"
    1.19 +#include "SkScript2.h"
    1.20 +#include "SkScriptCallBack.h"
    1.21 +
    1.22 +static const SkDisplayEnumMap gEnumMaps[] = {
    1.23 +    { SkType_AddMode, "indirect|immediate" },
    1.24 +    { SkType_Align, "left|center|right" },
    1.25 +    { SkType_ApplyMode, "immediate|once" },
    1.26 +    { SkType_ApplyTransition, "reverse" },
    1.27 +    { SkType_BitmapEncoding, "jpeg|png" },
    1.28 +    { SkType_BitmapFormat, "none|A1|A8|Index8|RGB16|RGB32" },
    1.29 +    { SkType_Boolean, "false|true" },
    1.30 +    { SkType_Cap, "butt|round|square" },
    1.31 +    { SkType_EventCode, "none|up|down|left|right|back|end|OK|send|leftSoftKey|rightSoftKey|key0|key1|key2|key3|key4|key5|key6|key7|key8|key9|star|hash" },
    1.32 +    { SkType_EventKind, "none|keyChar|keyPress|mouseDown|mouseDrag|mouseMove|mouseUp|onEnd|onLoad|user" },
    1.33 +    { SkType_EventMode, "deferred|immediate" },
    1.34 +    { SkType_FillType, "winding|evenOdd" },
    1.35 +    { SkType_FilterType, "none|bilinear" },
    1.36 +    { SkType_FromPathMode, "normal|angle|position" },
    1.37 +    { SkType_Join, "miter|round|blunt" },
    1.38 +    { SkType_MaskFilterBlurStyle, "normal|solid|outer|inner" },
    1.39 +    { SkType_PathDirection, "cw|ccw" },
    1.40 +    { SkType_Style, "fill|stroke|strokeAndFill" },
    1.41 +    { SkType_TextBoxAlign, "start|center|end" },
    1.42 +    { SkType_TextBoxMode, "oneLine|lineBreak" },
    1.43 +    { SkType_TileMode, "clamp|repeat|mirror" },
    1.44 +    { SkType_Xfermode, "clear|src|dst|srcOver|dstOver|srcIn|dstIn|srcOut|dstOut|"
    1.45 +        "srcATop|dstATop|xor|darken|lighten" },
    1.46 +};
    1.47 +
    1.48 +static int gEnumMapCount = SK_ARRAY_COUNT(gEnumMaps);
    1.49 +
    1.50 +
    1.51 +class SkAnimatorScript_Box : public SkScriptCallBackConvert {
    1.52 +public:
    1.53 +    SkAnimatorScript_Box() {}
    1.54 +
    1.55 +    ~SkAnimatorScript_Box() {
    1.56 +        for (SkDisplayable** dispPtr = fTrackDisplayable.begin(); dispPtr < fTrackDisplayable.end(); dispPtr++)
    1.57 +            delete *dispPtr;
    1.58 +    }
    1.59 +
    1.60 +    virtual bool convert(SkOperand2::OpType type, SkOperand2* operand) {
    1.61 +        SkDisplayable* displayable;
    1.62 +        switch (type) {
    1.63 +            case SkOperand2::kArray: {
    1.64 +                SkDisplayArray* boxedValue = new SkDisplayArray(*operand->fArray);
    1.65 +                displayable = boxedValue;
    1.66 +                } break;
    1.67 +            case SkOperand2::kS32: {
    1.68 +                SkDisplayInt* boxedValue = new SkDisplayInt;
    1.69 +                displayable = boxedValue;
    1.70 +                boxedValue->value = operand->fS32;
    1.71 +                } break;
    1.72 +            case SkOperand2::kScalar: {
    1.73 +                SkDisplayFloat* boxedValue = new SkDisplayFloat;
    1.74 +                displayable = boxedValue;
    1.75 +                boxedValue->value = operand->fScalar;
    1.76 +                } break;
    1.77 +            case SkOperand2::kString: {
    1.78 +                SkDisplayString* boxedValue = new SkDisplayString(*operand->fString);
    1.79 +                displayable = boxedValue;
    1.80 +                } break;
    1.81 +            case SkOperand2::kObject:
    1.82 +                return true;
    1.83 +            default:
    1.84 +                SkASSERT(0);
    1.85 +                return false;
    1.86 +        }
    1.87 +        track(displayable);
    1.88 +        operand->fObject = (void*) displayable;
    1.89 +        return true;
    1.90 +    }
    1.91 +
    1.92 +    virtual SkOperand2::OpType getReturnType(int index) {
    1.93 +        return SkOperand2::kObject;
    1.94 +    }
    1.95 +
    1.96 +    virtual Type getType() const {
    1.97 +        return kBox;
    1.98 +    }
    1.99 +
   1.100 +    void track(SkDisplayable* displayable) {
   1.101 +        SkASSERT(fTrackDisplayable.find(displayable) < 0);
   1.102 +        *fTrackDisplayable.append() = displayable;
   1.103 +    }
   1.104 +
   1.105 +    SkTDDisplayableArray fTrackDisplayable;
   1.106 +};
   1.107 +
   1.108 +
   1.109 +class SkAnimatorScript_Enum : public SkScriptCallBackProperty {
   1.110 +public:
   1.111 +    SkAnimatorScript_Enum(const char* tokens) : fTokens(tokens) {}
   1.112 +
   1.113 +    virtual bool getConstValue(const char* name, int len, SkOperand2* value) {
   1.114 +        return SkAnimatorScript2::MapEnums(fTokens, name, len, &value->fS32);
   1.115 +    }
   1.116 +
   1.117 +private:
   1.118 +    const char* fTokens;
   1.119 +};
   1.120 +
   1.121 +    // !!! if type is string, call invoke
   1.122 +    // if any other type, return original value
   1.123 +        // distinction is undone: could do this by returning index == 0 only if param is string
   1.124 +        // still, caller of getParamTypes will attempt to convert param to string (I guess)
   1.125 +class SkAnimatorScript_Eval : public SkScriptCallBackFunction {
   1.126 +public:
   1.127 +    SkAnimatorScript_Eval(SkAnimatorScript2* engine) : fEngine(engine) {}
   1.128 +
   1.129 +    virtual bool getIndex(const char* name, int len, size_t* result) {
   1.130 +        if (SK_LITERAL_STR_EQUAL("eval", name, len) != 0)
   1.131 +            return false;
   1.132 +        *result = 0;
   1.133 +        return true;
   1.134 +    }
   1.135 +
   1.136 +    virtual void getParamTypes(SkIntArray(SkOperand2::OpType)* types) {
   1.137 +        types->setCount(1);
   1.138 +        SkOperand2::OpType* type = types->begin();
   1.139 +        type[0] = SkOperand2::kString;
   1.140 +    }
   1.141 +
   1.142 +    virtual bool invoke(size_t index, SkOpArray* params, SkOperand2* answer) {
   1.143 +        SkAnimatorScript2 engine(fEngine->getMaker(), fEngine->getWorking(),
   1.144 +            SkAnimatorScript2::ToDisplayType(fEngine->getReturnType()));
   1.145 +        SkOperand2* op = params->begin();
   1.146 +        const char* script = op->fString->c_str();
   1.147 +        SkScriptValue2 value;
   1.148 +        return engine.evaluateScript(&script, &value);
   1.149 +        SkASSERT(value.fType == fEngine->getReturnType());
   1.150 +        *answer = value.fOperand;
   1.151 +        // !!! incomplete ?
   1.152 +        return true;
   1.153 +    }
   1.154 +
   1.155 +private:
   1.156 +    SkAnimatorScript2* fEngine;
   1.157 +};
   1.158 +
   1.159 +class SkAnimatorScript_ID : public SkScriptCallBackProperty {
   1.160 +public:
   1.161 +    SkAnimatorScript_ID(SkAnimatorScript2* engine) : fEngine(engine) {}
   1.162 +
   1.163 +    virtual bool getIndex(const char* token, int len, size_t* result) {
   1.164 +        SkDisplayable* displayable;
   1.165 +        bool success = fEngine->getMaker().find(token, len, &displayable);
   1.166 +        if (success == false) {
   1.167 +            *result = 0;
   1.168 +        } else {
   1.169 +            *result = (size_t) displayable;
   1.170 +            SkDisplayable* working = fEngine->getWorking();
   1.171 +            if (displayable->canContainDependents() && working && working->isAnimate()) {
   1.172 +                SkAnimateBase* animator = (SkAnimateBase*) working;
   1.173 +                if (animator->isDynamic()) {
   1.174 +                    SkDisplayDepend* depend = (SkDisplayDepend* ) displayable;
   1.175 +                    depend->addDependent(working);
   1.176 +                }
   1.177 +            }
   1.178 +        }
   1.179 +        return true;
   1.180 +    }
   1.181 +
   1.182 +    virtual bool getResult(size_t ref, SkOperand2* answer) {
   1.183 +        answer->fObject = (void*) ref;
   1.184 +        return true;
   1.185 +    }
   1.186 +
   1.187 +    virtual SkOperand2::OpType getReturnType(size_t index) {
   1.188 +        return index == 0 ? SkOperand2::kString : SkOperand2::kObject;
   1.189 +    }
   1.190 +
   1.191 +private:
   1.192 +    SkAnimatorScript2* fEngine;
   1.193 +};
   1.194 +
   1.195 +
   1.196 +class SkAnimatorScript_Member : public SkScriptCallBackMember {
   1.197 +public:
   1.198 +
   1.199 +    SkAnimatorScript_Member(SkAnimatorScript2* engine) : fEngine(engine) {}
   1.200 +
   1.201 +    bool getMemberReference(const char* member, size_t len, void* object, SkScriptValue2* ref) {
   1.202 +        SkDisplayable* displayable = (SkDisplayable*) object;
   1.203 +        SkString name(member, len);
   1.204 +        SkDisplayable* named = displayable->contains(name);
   1.205 +        if (named) {
   1.206 +            ref->fType = SkOperand2::kObject;
   1.207 +            ref->fOperand.fObject = named;
   1.208 +            return true;
   1.209 +        }
   1.210 +        const SkMemberInfo* info = displayable->getMember(name.c_str());
   1.211 +        if (info == NULL)
   1.212 +            return false;    // !!! add additional error info?
   1.213 +        ref->fType = SkAnimatorScript2::ToOpType(info->getType());
   1.214 +        ref->fOperand.fObject = (void*) info;
   1.215 +        return true;
   1.216 +    }
   1.217 +
   1.218 +    bool invoke(size_t ref, void* object, SkOperand2* value) {
   1.219 +        const SkMemberInfo* info = (const SkMemberInfo* ) ref;
   1.220 +        SkDisplayable* displayable = (SkDisplayable*) object;
   1.221 +        if (info->fType == SkType_MemberProperty) {
   1.222 +            if (displayable->getProperty2(info->propertyIndex(), value) == false) {
   1.223 +                return false;
   1.224 +            }
   1.225 +        }
   1.226 +        return fEngine->evalMemberCommon(info, displayable, value);
   1.227 +    }
   1.228 +
   1.229 +    SkAnimatorScript2* fEngine;
   1.230 +};
   1.231 +
   1.232 +
   1.233 +class SkAnimatorScript_MemberFunction : public SkScriptCallBackMemberFunction {
   1.234 +public:
   1.235 +    SkAnimatorScript_MemberFunction(SkAnimatorScript2* engine) : fEngine(engine) {}
   1.236 +
   1.237 +    bool getMemberReference(const char* member, size_t len, void* object, SkScriptValue2* ref) {
   1.238 +        SkDisplayable* displayable = (SkDisplayable*) object;
   1.239 +        SkString name(member, len);
   1.240 +        const SkMemberInfo* info = displayable->getMember(name.c_str());
   1.241 +        if (info == NULL || info->fType != SkType_MemberFunction)
   1.242 +            return false;    // !!! add additional error info?
   1.243 +        ref->fType = SkAnimatorScript2::ToOpType(info->getType());
   1.244 +        ref->fOperand.fObject = (void*) info;
   1.245 +        return true;
   1.246 +    }
   1.247 +
   1.248 +    virtual void getParamTypes(SkIntArray(SkOperand2::OpType)* types) {
   1.249 +        types->setCount(3);
   1.250 +        SkOperand2::OpType* type = types->begin();
   1.251 +        type[0] = type[1] = type[2] = SkOperand2::kS32;
   1.252 +    }
   1.253 +
   1.254 +    bool invoke(size_t ref, void* object, SkOpArray* params, SkOperand2* value)
   1.255 +    {
   1.256 +        const SkMemberInfo* info = (const SkMemberInfo* ) ref;
   1.257 +        SkDisplayable* displayable = (SkDisplayable*) object;
   1.258 +        displayable->executeFunction2(displayable, info->functionIndex(), params, info->getType(),
   1.259 +            value);
   1.260 +        return fEngine->evalMemberCommon(info, displayable, value);
   1.261 +    }
   1.262 +
   1.263 +    SkAnimatorScript2* fEngine;
   1.264 +};
   1.265 +
   1.266 +
   1.267 +class SkAnimatorScript_NamedColor : public SkScriptCallBackProperty {
   1.268 +public:
   1.269 +    virtual bool getConstValue(const char* name, int len, SkOperand2* value) {
   1.270 +        return SkParse::FindNamedColor(name, len, (SkColor*) &value->fS32) != NULL;
   1.271 +    }
   1.272 +};
   1.273 +
   1.274 +
   1.275 +class SkAnimatorScript_RGB : public SkScriptCallBackFunction {
   1.276 +public:
   1.277 +    virtual bool getIndex(const char* name, int len, size_t* result) {
   1.278 +        if (SK_LITERAL_STR_EQUAL("rgb", name, len) != 0)
   1.279 +            return false;
   1.280 +        *result = 0;
   1.281 +        return true;
   1.282 +    }
   1.283 +
   1.284 +    virtual void getParamTypes(SkIntArray(SkOperand2::OpType)* types) {
   1.285 +        types->setCount(3);
   1.286 +        SkOperand2::OpType* type = types->begin();
   1.287 +        type[0] = type[1] = type[2] = SkOperand2::kS32;
   1.288 +    }
   1.289 +
   1.290 +    virtual bool invoke(size_t index, SkOpArray* params, SkOperand2* answer) {
   1.291 +        SkASSERT(index == 0);
   1.292 +        unsigned result = 0xFF000000;
   1.293 +        int shift = 16;
   1.294 +        for (int index = 0; index < 3; index++) {
   1.295 +            result |= SkClampMax(params->begin()[index].fS32, 255) << shift;
   1.296 +            shift -= 8;
   1.297 +        }
   1.298 +        answer->fS32 = result;
   1.299 +        return true;
   1.300 +    }
   1.301 +
   1.302 +};
   1.303 +
   1.304 +
   1.305 +class SkAnimatorScript_Unbox : public SkScriptCallBackConvert {
   1.306 +public:
   1.307 +    SkAnimatorScript_Unbox(SkAnimatorScript2* engine) : fEngine(engine) {}
   1.308 +
   1.309 +    virtual bool convert(SkOperand2::OpType type, SkOperand2* operand) {
   1.310 +        SkASSERT(type == SkOperand2::kObject);
   1.311 +        SkDisplayable* displayable = (SkDisplayable*) operand->fObject;
   1.312 +        switch (displayable->getType()) {
   1.313 +            case SkType_Array: {
   1.314 +                SkDisplayArray* boxedValue = (SkDisplayArray*) displayable;
   1.315 +                operand->fArray = new SkOpArray(SkAnimatorScript2::ToOpType(boxedValue->values.getType()));
   1.316 +                int count = boxedValue->values.count();
   1.317 +                operand->fArray->setCount(count);
   1.318 +                memcpy(operand->fArray->begin(), boxedValue->values.begin(), count * sizeof(SkOperand2));
   1.319 +                fEngine->track(operand->fArray);
   1.320 +                } break;
   1.321 +            case SkType_Boolean: {
   1.322 +                SkDisplayBoolean* boxedValue = (SkDisplayBoolean*) displayable;
   1.323 +                operand->fS32 = boxedValue->value;
   1.324 +                } break;
   1.325 +            case SkType_Int: {
   1.326 +                SkDisplayInt* boxedValue = (SkDisplayInt*) displayable;
   1.327 +                operand->fS32 = boxedValue->value;
   1.328 +                } break;
   1.329 +            case SkType_Float: {
   1.330 +                SkDisplayFloat* boxedValue = (SkDisplayFloat*) displayable;
   1.331 +                operand->fScalar = boxedValue->value;
   1.332 +                } break;
   1.333 +            case SkType_String: {
   1.334 +                SkDisplayString* boxedValue = (SkDisplayString*) displayable;
   1.335 +                operand->fString = SkNEW_ARGS(SkString, (boxedValue->value));
   1.336 +                } break;
   1.337 +            default: {
   1.338 +                const char* id;
   1.339 +                bool success = fEngine->getMaker().findKey(displayable, &id);
   1.340 +                SkASSERT(success);
   1.341 +                operand->fString = SkNEW_ARGS(SkString, (id));
   1.342 +            }
   1.343 +        }
   1.344 +        return true;
   1.345 +    }
   1.346 +
   1.347 +    virtual SkOperand2::OpType getReturnType(int /*index*/, SkOperand2* operand) {
   1.348 +        SkDisplayable* displayable = (SkDisplayable*) operand->fObject;
   1.349 +        switch (displayable->getType()) {
   1.350 +            case SkType_Array:
   1.351 +                return SkOperand2::kArray;
   1.352 +            case SkType_Int:
   1.353 +                return SkOperand2::kS32;
   1.354 +            case SkType_Float:
   1.355 +                return SkOperand2::kScalar;
   1.356 +            case SkType_String:
   1.357 +            default:
   1.358 +                return SkOperand2::kString;
   1.359 +        }
   1.360 +    }
   1.361 +
   1.362 +    virtual Type getType() const {
   1.363 +        return kUnbox;
   1.364 +    }
   1.365 +
   1.366 +    SkAnimatorScript2* fEngine;
   1.367 +};
   1.368 +
   1.369 +SkAnimatorScript2::SkAnimatorScript2(SkAnimateMaker& maker, SkDisplayable* working, SkDisplayTypes type) :
   1.370 +        SkScriptEngine2(ToOpType(type)), fMaker(maker), fWorking(working) {
   1.371 +    *fCallBackArray.append() = new SkAnimatorScript_Member(this);
   1.372 +    *fCallBackArray.append() = new SkAnimatorScript_MemberFunction(this);
   1.373 +    *fCallBackArray.append() = new SkAnimatorScript_Box();
   1.374 +    *fCallBackArray.append() = new SkAnimatorScript_Unbox(this);
   1.375 +    *fCallBackArray.append() = new SkAnimatorScript_ID(this);
   1.376 +    if (type == SkType_ARGB) {
   1.377 +        *fCallBackArray.append() = new SkAnimatorScript_RGB();
   1.378 +        *fCallBackArray.append() = new SkAnimatorScript_NamedColor();
   1.379 +    }
   1.380 +    if (SkDisplayType::IsEnum(&maker, type)) {
   1.381 +        // !!! for SpiderMonkey, iterate through the enum values, and map them to globals
   1.382 +        const SkDisplayEnumMap& map = GetEnumValues(type);
   1.383 +        *fCallBackArray.append() = new SkAnimatorScript_Enum(map.fValues);
   1.384 +    }
   1.385 +    *fCallBackArray.append() = new SkAnimatorScript_Eval(this);
   1.386 +#if 0        // !!! no extra support for now
   1.387 +    for (SkExtras** extraPtr = maker.fExtras.begin(); extraPtr < maker.fExtras.end(); extraPtr++) {
   1.388 +        SkExtras* extra = *extraPtr;
   1.389 +        if (extra->fExtraCallBack)
   1.390 +            *fCallBackArray.append() = new propertyCallBack(extra->fExtraCallBack, extra->fExtraStorage);
   1.391 +    }
   1.392 +#endif
   1.393 +}
   1.394 +
   1.395 +SkAnimatorScript2::~SkAnimatorScript2() {
   1.396 +    SkScriptCallBack** end = fCallBackArray.end();
   1.397 +    for (SkScriptCallBack** ptr = fCallBackArray.begin(); ptr < end; ptr++)
   1.398 +        delete *ptr;
   1.399 +}
   1.400 +
   1.401 +bool SkAnimatorScript2::evalMemberCommon(const SkMemberInfo* info,
   1.402 +        SkDisplayable* displayable, SkOperand2* value) {
   1.403 +    SkDisplayTypes original;
   1.404 +    SkDisplayTypes type = original = (SkDisplayTypes) info->getType();
   1.405 +    if (info->fType == SkType_Array)
   1.406 +        type = SkType_Array;
   1.407 +    switch (type) {
   1.408 +        case SkType_ARGB:
   1.409 +            type = SkType_Int;
   1.410 +        case SkType_Boolean:
   1.411 +        case SkType_Int:
   1.412 +        case SkType_MSec:
   1.413 +        case SkType_Float:
   1.414 +            SkASSERT(info->getCount() == 1);
   1.415 +            if (info->fType != SkType_MemberProperty && info->fType != SkType_MemberFunction)
   1.416 +                value->fS32 = *(int32_t*) info->memberData(displayable);    // OK for SkScalar too
   1.417 +            if (type == SkType_MSec) {
   1.418 +                value->fScalar = SkScalarDiv((SkScalar) value->fS32, 1000); // dividing two ints is the same as dividing two scalars
   1.419 +                type = SkType_Float;
   1.420 +            }
   1.421 +            break;
   1.422 +        case SkType_String: {
   1.423 +            SkString* displayableString;
   1.424 +            if (info->fType != SkType_MemberProperty && info->fType != SkType_MemberFunction) {
   1.425 +                info->getString(displayable, &displayableString);
   1.426 +                value->fString = new SkString(*displayableString);
   1.427 +            }
   1.428 +            } break;
   1.429 +        case SkType_Array: {
   1.430 +            SkASSERT(info->fType != SkType_MemberProperty); // !!! incomplete
   1.431 +            SkTDOperandArray* displayableArray = (SkTDOperandArray*) info->memberData(displayable);
   1.432 +            if (displayable->getType() == SkType_Array) {
   1.433 +                SkDisplayArray* typedArray = (SkDisplayArray*) displayable;
   1.434 +                original = typedArray->values.getType();
   1.435 +            }
   1.436 +            SkASSERT(original != SkType_Unknown);
   1.437 +            SkOpArray* array = value->fArray = new SkOpArray(ToOpType(original));
   1.438 +            track(array);
   1.439 +            int count = displayableArray->count();
   1.440 +            if (count > 0) {
   1.441 +                array->setCount(count);
   1.442 +                memcpy(array->begin(), displayableArray->begin(), count * sizeof(SkOperand2));
   1.443 +            }
   1.444 +            } break;
   1.445 +        default:
   1.446 +            SkASSERT(0); // unimplemented
   1.447 +    }
   1.448 +    return true;
   1.449 +}
   1.450 +
   1.451 +const SkDisplayEnumMap& SkAnimatorScript2::GetEnumValues(SkDisplayTypes type) {
   1.452 +    int index = SkTSearch<SkDisplayTypes>(&gEnumMaps[0].fType, gEnumMapCount, type,
   1.453 +        sizeof(SkDisplayEnumMap));
   1.454 +    SkASSERT(index >= 0);
   1.455 +    return gEnumMaps[index];
   1.456 +}
   1.457 +
   1.458 +SkDisplayTypes SkAnimatorScript2::ToDisplayType(SkOperand2::OpType type) {
   1.459 +    int val = type;
   1.460 +    switch (val) {
   1.461 +        case SkOperand2::kNoType:
   1.462 +            return SkType_Unknown;
   1.463 +        case SkOperand2::kS32:
   1.464 +            return SkType_Int;
   1.465 +        case SkOperand2::kScalar:
   1.466 +            return SkType_Float;
   1.467 +        case SkOperand2::kString:
   1.468 +            return SkType_String;
   1.469 +        case SkOperand2::kArray:
   1.470 +            return SkType_Array;
   1.471 +        case SkOperand2::kObject:
   1.472 +            return SkType_Displayable;
   1.473 +        default:
   1.474 +            SkASSERT(0);
   1.475 +            return SkType_Unknown;
   1.476 +    }
   1.477 +}
   1.478 +
   1.479 +SkOperand2::OpType SkAnimatorScript2::ToOpType(SkDisplayTypes type) {
   1.480 +    if (SkDisplayType::IsDisplayable(NULL /* fMaker */, type))
   1.481 +        return SkOperand2::kObject;
   1.482 +    if (SkDisplayType::IsEnum(NULL /* fMaker */, type))
   1.483 +        return SkOperand2::kS32;
   1.484 +    switch (type) {
   1.485 +        case SkType_ARGB:
   1.486 +        case SkType_MSec:
   1.487 +        case SkType_Int:
   1.488 +            return SkOperand2::kS32;
   1.489 +        case SkType_Float:
   1.490 +        case SkType_Point:
   1.491 +        case SkType_3D_Point:
   1.492 +            return SkOperand2::kScalar;
   1.493 +        case SkType_Base64:
   1.494 +        case SkType_DynamicString:
   1.495 +        case SkType_String:
   1.496 +            return SkOperand2::kString;
   1.497 +        case SkType_Array:
   1.498 +            return SkOperand2::kArray;
   1.499 +        case SkType_Unknown:
   1.500 +            return SkOperand2::kNoType;
   1.501 +        default:
   1.502 +            SkASSERT(0);
   1.503 +            return SkOperand2::kNoType;
   1.504 +    }
   1.505 +}
   1.506 +
   1.507 +bool SkAnimatorScript2::MapEnums(const char* ptr, const char* match, size_t len, int* value) {
   1.508 +    int index = 0;
   1.509 +    bool more = true;
   1.510 +    do {
   1.511 +        const char* last = strchr(ptr, '|');
   1.512 +        if (last == NULL) {
   1.513 +            last = &ptr[strlen(ptr)];
   1.514 +            more = false;
   1.515 +        }
   1.516 +        size_t length = last - ptr;
   1.517 +        if (len == length && strncmp(ptr, match, length) == 0) {
   1.518 +            *value = index;
   1.519 +            return true;
   1.520 +        }
   1.521 +        index++;
   1.522 +        ptr = last + 1;
   1.523 +    } while (more);
   1.524 +    return false;
   1.525 +}
   1.526 +
   1.527 +#if defined SK_DEBUG
   1.528 +
   1.529 +#include "SkAnimator.h"
   1.530 +
   1.531 +static const char scriptTestSetup[]  =
   1.532 +"<screenplay>"
   1.533 +    "<apply>"
   1.534 +        "<paint>"
   1.535 +            "<emboss id='emboss' direction='[1,1,1]'  />"
   1.536 +        "</paint>"
   1.537 +        "<animateField id='animation' field='direction' target='emboss' from='[1,1,1]' to='[-1,1,1]' dur='1'/>"
   1.538 +        "<set lval='direction[0]' target='emboss' to='-1' />"
   1.539 +    "</apply>"
   1.540 +    "<color id='testColor' color='0 ? rgb(0,0,0) : rgb(255,255,255)' />"
   1.541 +    "<color id='xColor' color='rgb(12,34,56)' />"
   1.542 +    "<typedArray id='emptyArray' />"
   1.543 +    "<typedArray id='intArray' values='[1, 4, 6]' />"
   1.544 +    "<s32 id='idx' value='2' />"
   1.545 +    "<s32 id='idy' value='2' />"
   1.546 +    "<string id='alpha' value='abc' />"
   1.547 +    "<rectangle id='testRect' left='Math.cos(0)' top='2' right='12' bottom='5' />"
   1.548 +    "<event id='evt'>"
   1.549 +        "<input name='x' />"
   1.550 +        "<apply scope='idy'>"
   1.551 +            "<set field='value' to='evt.x.s32' />"
   1.552 +        "</apply>"
   1.553 +    "</event>"
   1.554 +"</screenplay>";
   1.555 +
   1.556 +static const SkScriptNAnswer scriptTests[]  = {
   1.557 +    {    "alpha+alpha", SkType_String, 0, 0, "abcabc" },
   1.558 +    {    "0 ? Math.sin(0) : 1", SkType_Int, 1 },
   1.559 +    {    "intArray[4]", SkType_Unknown },
   1.560 +    {    "emptyArray[4]", SkType_Unknown },
   1.561 +    {    "idx", SkType_Int, 2 },
   1.562 +    {    "intArray.length", SkType_Int, 3 },
   1.563 +    {    "intArray.values[0]", SkType_Int, 1 },
   1.564 +    {    "intArray[0]", SkType_Int, 1 },
   1.565 +    {    "idx.value", SkType_Int, 2 },
   1.566 +    {    "alpha.value", SkType_String, 0, 0, "abc" },
   1.567 +    {    "alpha", SkType_String, 0, 0, "abc" },
   1.568 +    {    "alpha.value+alpha.value", SkType_String, 0, 0, "abcabc" },
   1.569 +    {    "alpha+idx", SkType_String, 0, 0, "abc2" },
   1.570 +    {    "idx+alpha", SkType_String, 0, 0, "2abc" },
   1.571 +    {    "intArray[idx]", SkType_Int, 6 },
   1.572 +    {    "alpha.slice(1,2)", SkType_String, 0, 0, "b" },
   1.573 +    {    "alpha.value.slice(1,2)", SkType_String, 0, 0, "b" },
   1.574 +    {    "Math.sin(0)", SkType_Float, 0, SkIntToScalar(0) },
   1.575 +    {    "testRect.left+2", SkType_Float, 0, SkIntToScalar(3) },
   1.576 +    {    "0 ? intArray[0] : 1", SkType_Int, 1 },
   1.577 +    {    "0 ? intArray.values[0] : 1", SkType_Int, 1 },
   1.578 +    {    "0 ? idx : 1", SkType_Int, 1 },
   1.579 +    {    "0 ? idx.value : 1", SkType_Int, 1 },
   1.580 +    {    "0 ? alpha.slice(1,2) : 1", SkType_Int, 1 },
   1.581 +    {    "0 ? alpha.value.slice(1,2) : 1", SkType_Int, 1 },
   1.582 +    { "idy", SkType_Int, 3 }
   1.583 +};
   1.584 +
   1.585 +#define SkScriptNAnswer_testCount    SK_ARRAY_COUNT(scriptTests)
   1.586 +
   1.587 +void SkAnimatorScript2::UnitTest() {
   1.588 +#if defined(SK_SUPPORT_UNITTEST)
   1.589 +    SkAnimator animator;
   1.590 +    SkASSERT(animator.decodeMemory(scriptTestSetup, sizeof(scriptTestSetup)-1));
   1.591 +    SkEvent evt;
   1.592 +    evt.setString("id", "evt");
   1.593 +    evt.setS32("x", 3);
   1.594 +    animator.doUserEvent(evt);
   1.595 +    // set up animator with memory script above, then run value tests
   1.596 +    for (int index = 0; index < SkScriptNAnswer_testCount; index++) {
   1.597 +        SkAnimatorScript2 engine(*animator.fMaker, NULL, scriptTests[index].fType);
   1.598 +        SkScriptValue2 value;
   1.599 +        const char* script = scriptTests[index].fScript;
   1.600 +        bool success = engine.evaluateScript(&script, &value);
   1.601 +        if (success == false) {
   1.602 +            SkASSERT(scriptTests[index].fType == SkType_Unknown);
   1.603 +            continue;
   1.604 +        }
   1.605 +        SkASSERT(value.fType == ToOpType(scriptTests[index].fType));
   1.606 +        SkScalar error;
   1.607 +        switch (value.fType) {
   1.608 +            case SkOperand2::kS32:
   1.609 +                SkASSERT(value.fOperand.fS32 == scriptTests[index].fIntAnswer);
   1.610 +                break;
   1.611 +            case SkOperand2::kScalar:
   1.612 +                error = SkScalarAbs(value.fOperand.fScalar - scriptTests[index].fScalarAnswer);
   1.613 +                SkASSERT(error < SK_Scalar1 / 10000);
   1.614 +                break;
   1.615 +            case SkOperand2::kString:
   1.616 +                SkASSERT(value.fOperand.fString->equals(scriptTests[index].fStringAnswer));
   1.617 +                break;
   1.618 +            default:
   1.619 +                SkASSERT(0);
   1.620 +        }
   1.621 +    }
   1.622 +#endif
   1.623 +}
   1.624 +
   1.625 +#endif

mercurial