Home | History | Annotate | Download | only in animator
      1 
      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  */
      8 
      9 
     10 #include "SkMemberInfo.h"
     11 #include "SkAnimateMaker.h"
     12 #include "SkAnimatorScript.h"
     13 #include "SkBase64.h"
     14 #include "SkCamera.h"
     15 #include "SkDisplayable.h"
     16 #include "SkDisplayTypes.h"
     17 #include "SkDraw3D.h"
     18 #include "SkDrawColor.h"
     19 #include "SkParse.h"
     20 #include "SkScript.h"
     21 #include "SkTSearch.h"
     22 #include "SkTypedArray.h"
     23 
     24 size_t SkMemberInfo::GetSize(SkDisplayTypes type) { // size of simple types only
     25     size_t byteSize;
     26     switch (type) {
     27         case SkType_ARGB:
     28             byteSize = sizeof(SkColor);
     29             break;
     30         case SkType_AddMode:
     31         case SkType_Align:
     32         case SkType_ApplyMode:
     33         case SkType_ApplyTransition:
     34         case SkType_BitmapEncoding:
     35         case SkType_Boolean:
     36         case SkType_Cap:
     37         case SkType_EventCode:
     38         case SkType_EventKind:
     39         case SkType_EventMode:
     40         case SkType_FilterType:
     41         case SkType_FontStyle:
     42         case SkType_FromPathMode:
     43         case SkType_Join:
     44         case SkType_MaskFilterBlurStyle:
     45         case SkType_PathDirection:
     46         case SkType_Style:
     47         case SkType_TileMode:
     48         case SkType_Xfermode:
     49             byteSize = sizeof(int);
     50             break;
     51         case SkType_Base64: // assume base64 data is always const, copied by ref
     52         case SkType_Displayable:
     53         case SkType_Drawable:
     54         case SkType_Matrix:
     55             byteSize = sizeof(void*);
     56             break;
     57         case SkType_MSec:
     58             byteSize = sizeof(SkMSec);
     59             break;
     60         case SkType_Point:
     61             byteSize = sizeof(SkPoint);
     62             break;
     63         case SkType_3D_Point:
     64             byteSize = sizeof(Sk3D_Point);
     65             break;
     66         case SkType_Int:
     67             byteSize = sizeof(int32_t);
     68             break;
     69         case SkType_Float:
     70             byteSize = sizeof(SkScalar);
     71             break;
     72         case SkType_DynamicString:
     73         case SkType_String:
     74             byteSize = sizeof(SkString);    // assume we'll copy by reference, not value
     75             break;
     76         default:
     77 //          SkASSERT(0);
     78             byteSize = 0;
     79     }
     80     return byteSize;
     81 }
     82 
     83 bool SkMemberInfo::getArrayValue(const SkDisplayable* displayable, int index, SkOperand* value) const {
     84     SkASSERT(fType != SkType_String && fType != SkType_MemberProperty);
     85     char* valuePtr = (char*) *(SkOperand**) memberData(displayable);
     86     SkDisplayTypes type = (SkDisplayTypes) 0;
     87     if (displayable->getType() == SkType_Array) {
     88         SkDisplayArray* dispArray = (SkDisplayArray*) displayable;
     89         if (dispArray->values.count() <= index)
     90             return false;
     91         type = dispArray->values.getType();
     92     } else {
     93         SkASSERT(0); // incomplete
     94     }
     95     size_t byteSize = GetSize(type);
     96     memcpy(value, valuePtr + index * byteSize, byteSize);
     97     return true;
     98 }
     99 
    100 size_t SkMemberInfo::getSize(const SkDisplayable* displayable) const {
    101     size_t byteSize;
    102     switch (fType) {
    103         case SkType_MemberProperty:
    104             byteSize = GetSize(propertyType());
    105             break;
    106         case SkType_Array: {
    107             SkDisplayTypes type;
    108             if (displayable == NULL)
    109                 return sizeof(int);
    110             if (displayable->getType() == SkType_Array) {
    111                 SkDisplayArray* dispArray = (SkDisplayArray*) displayable;
    112                 type = dispArray->values.getType();
    113             } else
    114                 type = propertyType();
    115             SkTDOperandArray* array = (SkTDOperandArray*) memberData(displayable);
    116             byteSize = GetSize(type) * array->count();
    117             } break;
    118         default:
    119             byteSize = GetSize((SkDisplayTypes) fType);
    120     }
    121     return byteSize;
    122 }
    123 
    124 void SkMemberInfo::getString(const SkDisplayable* displayable, SkString** string) const {
    125     if (fType == SkType_MemberProperty) {
    126         SkScriptValue value;
    127         displayable->getProperty(propertyIndex(), &value);
    128         SkASSERT(value.fType == SkType_String);
    129         *string = value.fOperand.fString;
    130         return;
    131     }
    132     SkASSERT(fCount == sizeof(SkString) / sizeof(SkScalar));
    133     SkASSERT(fType == SkType_String || fType == SkType_DynamicString);
    134     void* valuePtr = memberData(displayable);
    135     *string = (SkString*) valuePtr;
    136 }
    137 
    138 void SkMemberInfo::getValue(const SkDisplayable* displayable, SkOperand value[], int count) const {
    139     SkASSERT(fType != SkType_String && fType != SkType_MemberProperty);
    140     SkASSERT(count == fCount);
    141     void* valuePtr = memberData(displayable);
    142     size_t byteSize = getSize(displayable);
    143     SkASSERT(sizeof(value[0].fScalar) == sizeof(value[0])); // no support for 64 bit pointers, yet
    144     memcpy(value, valuePtr, byteSize);
    145 }
    146 
    147 void SkMemberInfo::setString(SkDisplayable* displayable, SkString* value) const {
    148     SkString* string = (SkString*) memberData(displayable);
    149     string->set(*value);
    150     displayable->dirty();
    151 }
    152 
    153 void SkMemberInfo::setValue(SkDisplayable* displayable, const SkOperand values[],
    154                             int count) const {
    155     SkASSERT(sizeof(values[0].fScalar) == sizeof(values[0]));   // no support for 64 bit pointers, yet
    156     char* dst = (char*) memberData(displayable);
    157     if (fType == SkType_Array) {
    158         SkTDScalarArray* array = (SkTDScalarArray* ) dst;
    159         array->setCount(count);
    160         dst = (char*) array->begin();
    161     }
    162     memcpy(dst, values, count * sizeof(SkOperand));
    163     displayable->dirty();
    164 }
    165 
    166 
    167 static inline bool is_between(int c, int min, int max)
    168 {
    169     return (unsigned)(c - min) <= (unsigned)(max - min);
    170 }
    171 
    172 static inline bool is_hex(int c)
    173 {
    174     if (is_between(c, '0', '9'))
    175         return true;
    176     c |= 0x20;  // make us lower-case
    177     if (is_between(c, 'a', 'f'))
    178         return true;
    179     return false;
    180 }
    181 
    182 
    183 bool SkMemberInfo::setValue(SkAnimateMaker& maker, SkTDOperandArray* arrayStorage,
    184     int storageOffset, int maxStorage, SkDisplayable* displayable, SkDisplayTypes outType,
    185     const char rawValue[], size_t rawValueLen) const
    186 {
    187     SkString valueStr(rawValue, rawValueLen);
    188     SkScriptValue scriptValue;
    189     scriptValue.fType = SkType_Unknown;
    190     scriptValue.fOperand.fS32 = 0;
    191     SkDisplayTypes type = getType();
    192     SkAnimatorScript engine(maker, displayable, type);
    193     if (arrayStorage)
    194         displayable = NULL;
    195     bool success = true;
    196     void* untypedStorage = NULL;
    197     if (displayable && fType != SkType_MemberProperty && fType != SkType_MemberFunction)
    198         untypedStorage = (SkTDOperandArray*) memberData(displayable);
    199 
    200     if (type == SkType_ARGB) {
    201         // for both SpiderMonkey and SkiaScript, substitute any #xyz or #xxyyzz first
    202             // it's enough to expand the colors into 0xFFxxyyzz
    203         const char* poundPos;
    204         while ((poundPos = strchr(valueStr.c_str(), '#')) != NULL) {
    205             size_t offset = poundPos - valueStr.c_str();
    206             if (valueStr.size() - offset < 4)
    207                 break;
    208             char r = poundPos[1];
    209             char g = poundPos[2];
    210             char b = poundPos[3];
    211             if (is_hex(r) == false || is_hex(g) == false || is_hex(b) == false)
    212                 break;
    213             char hex = poundPos[4];
    214             if (is_hex(hex) == false) {
    215                 valueStr.insertUnichar(offset + 1, r);
    216                 valueStr.insertUnichar(offset + 3, g);
    217                 valueStr.insertUnichar(offset + 5, b);
    218             }
    219             *(char*) poundPos = '0'; // overwrite '#'
    220             valueStr.insert(offset + 1, "xFF");
    221         }
    222     }
    223     if (SkDisplayType::IsDisplayable(&maker, type) || SkDisplayType::IsEnum(&maker, type) || type == SkType_ARGB)
    224         goto scriptCommon;
    225     switch (type) {
    226         case SkType_String:
    227 #if 0
    228             if (displayable && displayable->isAnimate()) {
    229 
    230                 goto noScriptString;
    231             }
    232             if (strncmp(rawValue, "#string:", sizeof("#string:") - 1) == 0) {
    233                 SkASSERT(sizeof("string") == sizeof("script"));
    234                 char* stringHeader = valueStr.writable_str();
    235                 memcpy(&stringHeader[1], "script", sizeof("script") - 1);
    236                 rawValue = valueStr.c_str();
    237                 goto noScriptString;
    238             } else
    239 #endif
    240             if (strncmp(rawValue, "#script:", sizeof("#script:") - 1) != 0)
    241                 goto noScriptString;
    242             valueStr.remove(0, 8);
    243         case SkType_Unknown:
    244         case SkType_Int:
    245         case SkType_MSec:  // for the purposes of script, MSec is treated as a Scalar
    246         case SkType_Point:
    247         case SkType_3D_Point:
    248         case SkType_Float:
    249         case SkType_Array:
    250 scriptCommon: {
    251                 const char* script = valueStr.c_str();
    252                 success = engine.evaluateScript(&script, &scriptValue);
    253                 if (success == false) {
    254                     maker.setScriptError(engine);
    255                     return false;
    256                 }
    257             }
    258             SkASSERT(success);
    259             if (scriptValue.fType == SkType_Displayable) {
    260                 if (type == SkType_String) {
    261                     const char* charPtr = NULL;
    262                     maker.findKey(scriptValue.fOperand.fDisplayable, &charPtr);
    263                     scriptValue.fOperand.fString = new SkString(charPtr);
    264                     scriptValue.fType = SkType_String;
    265                     engine.SkScriptEngine::track(scriptValue.fOperand.fString);
    266                     break;
    267                 }
    268                 SkASSERT(SkDisplayType::IsDisplayable(&maker, type));
    269                 if (displayable)
    270                     displayable->setReference(this, scriptValue.fOperand.fDisplayable);
    271                 else
    272                     arrayStorage->begin()[0].fDisplayable = scriptValue.fOperand.fDisplayable;
    273                 return true;
    274             }
    275             if (type != scriptValue.fType) {
    276                 if (scriptValue.fType == SkType_Array) {
    277                     engine.forget(scriptValue.getArray());
    278                     goto writeStruct; // real structs have already been written by script
    279                 }
    280                 switch (type) {
    281                     case SkType_String:
    282                         success = engine.convertTo(SkType_String, &scriptValue);
    283                         break;
    284                     case SkType_MSec:
    285                     case SkType_Float:
    286                         success = engine.convertTo(SkType_Float, &scriptValue);
    287                         break;
    288                     case SkType_Int:
    289                         success = engine.convertTo(SkType_Int, &scriptValue);
    290                         break;
    291                     case SkType_Array:
    292                         success = engine.convertTo(arrayType(), &scriptValue);
    293                         // !!! incomplete; create array of appropriate type and add scriptValue to it
    294                         SkASSERT(0);
    295                         break;
    296                     case SkType_Displayable:
    297                     case SkType_Drawable:
    298                         return false;   // no way to convert other types to this
    299                     default:    // to avoid warnings
    300                         break;
    301                 }
    302                 if (success == false)
    303                     return false;
    304             }
    305             if (type == SkType_MSec)
    306                 scriptValue.fOperand.fMSec = SkScalarRoundToInt(scriptValue.fOperand.fScalar * 1000);
    307             scriptValue.fType = type;
    308         break;
    309         noScriptString:
    310         case SkType_DynamicString:
    311             if (fType == SkType_MemberProperty && displayable) {
    312                 SkString string(rawValue, rawValueLen);
    313                 SkScriptValue scriptValue;
    314                 scriptValue.fOperand.fString = &string;
    315                 scriptValue.fType = SkType_String;
    316                 displayable->setProperty(propertyIndex(), scriptValue);
    317             } else if (displayable) {
    318                 SkString* string = (SkString*) memberData(displayable);
    319                 string->set(rawValue, rawValueLen);
    320             } else {
    321                 SkASSERT(arrayStorage->count() == 1);
    322                 arrayStorage->begin()->fString->set(rawValue, rawValueLen);
    323             }
    324             goto dirty;
    325         case SkType_Base64: {
    326             SkBase64 base64;
    327             base64.decode(rawValue, rawValueLen);
    328             *(SkBase64* ) untypedStorage = base64;
    329             } goto dirty;
    330         default:
    331             SkASSERT(0);
    332             break;
    333     }
    334 //  if (SkDisplayType::IsStruct(type) == false)
    335     {
    336 writeStruct:
    337         if (writeValue(displayable, arrayStorage, storageOffset, maxStorage,
    338                 untypedStorage, outType, scriptValue)) {
    339                     maker.setErrorCode(SkDisplayXMLParserError::kUnexpectedType);
    340             return false;
    341         }
    342     }
    343 dirty:
    344     if (displayable)
    345         displayable->dirty();
    346     return true;
    347 }
    348 
    349 bool SkMemberInfo::setValue(SkAnimateMaker& maker, SkTDOperandArray* arrayStorage,
    350         int storageOffset, int maxStorage, SkDisplayable* displayable, SkDisplayTypes outType,
    351         SkString& raw) const {
    352     return setValue(maker, arrayStorage, storageOffset, maxStorage, displayable, outType, raw.c_str(),
    353         raw.size());
    354 }
    355 
    356 bool SkMemberInfo::writeValue(SkDisplayable* displayable, SkTDOperandArray* arrayStorage,
    357     int storageOffset, int maxStorage, void* untypedStorage, SkDisplayTypes outType,
    358     SkScriptValue& scriptValue) const
    359 {
    360     SkOperand* storage = untypedStorage ? (SkOperand*) untypedStorage : arrayStorage ?
    361         arrayStorage->begin() : NULL;
    362     if (storage)
    363         storage += storageOffset;
    364     SkDisplayTypes type = getType();
    365     if (fType == SkType_MemberProperty) {
    366         if(displayable)
    367             displayable->setProperty(propertyIndex(), scriptValue);
    368         else {
    369             SkASSERT(storageOffset < arrayStorage->count());
    370             switch (scriptValue.fType) {
    371                 case SkType_Boolean:
    372                 case SkType_Float:
    373                 case SkType_Int:
    374                     memcpy(&storage->fScalar, &scriptValue.fOperand.fScalar, sizeof(SkScalar));
    375                     break;
    376                 case SkType_Array:
    377                     memcpy(&storage->fScalar, scriptValue.fOperand.fArray->begin(), scriptValue.fOperand.fArray->count() * sizeof(SkScalar));
    378                     break;
    379                 case SkType_String:
    380                     storage->fString->set(*scriptValue.fOperand.fString);
    381                     break;
    382                 default:
    383                     SkASSERT(0);    // type isn't handled yet
    384             }
    385         }
    386     } else if (fType == SkType_MemberFunction) {
    387         SkASSERT(scriptValue.fType == SkType_Array);
    388         if (displayable)
    389             displayable->executeFunction(displayable, this, scriptValue.fOperand.fArray, NULL);
    390         else {
    391             int count = scriptValue.fOperand.fArray->count();
    392     //      SkASSERT(maxStorage == 0 || count == maxStorage);
    393             if (arrayStorage->count() == 2)
    394                 arrayStorage->setCount(2 * count);
    395             else {
    396                 storageOffset *= count;
    397                 SkASSERT(count + storageOffset <= arrayStorage->count());
    398             }
    399             memcpy(&(*arrayStorage)[storageOffset], scriptValue.fOperand.fArray->begin(), count * sizeof(SkOperand));
    400         }
    401 
    402     } else if (fType == SkType_Array) {
    403         SkTypedArray* destArray = (SkTypedArray*) (untypedStorage ? untypedStorage : arrayStorage);
    404         SkASSERT(destArray);
    405     //  destArray->setCount(0);
    406         if (scriptValue.fType != SkType_Array) {
    407             SkASSERT(type == scriptValue.fType);
    408     //      SkASSERT(storageOffset + 1 <= maxStorage);
    409             destArray->setCount(storageOffset + 1);
    410             (*destArray)[storageOffset] = scriptValue.fOperand;
    411         } else {
    412             if (type == SkType_Unknown) {
    413                 type = scriptValue.fOperand.fArray->getType();
    414                 destArray->setType(type);
    415             }
    416             SkASSERT(type == scriptValue.fOperand.fArray->getType());
    417             int count = scriptValue.fOperand.fArray->count();
    418     //      SkASSERT(storageOffset + count <= maxStorage);
    419             destArray->setCount(storageOffset + count);
    420             memcpy(destArray->begin() + storageOffset, scriptValue.fOperand.fArray->begin(), sizeof(SkOperand) * count);
    421         }
    422     } else if (type == SkType_String) {
    423         SkString* string = untypedStorage ? (SkString*) untypedStorage : (*arrayStorage)[storageOffset].fString;
    424         string->set(*scriptValue.fOperand.fString);
    425     } else if (type == SkType_ARGB && outType == SkType_Float) {
    426         SkTypedArray* array = scriptValue.fOperand.fArray;
    427         SkASSERT(scriptValue.fType == SkType_Int || scriptValue.fType == SkType_ARGB ||
    428             scriptValue.fType == SkType_Array);
    429         SkASSERT(scriptValue.fType != SkType_Array || (array != NULL &&
    430             array->getType() == SkType_Int));
    431         int numberOfColors = scriptValue.fType == SkType_Array ? array->count() : 1;
    432         int numberOfComponents = numberOfColors * 4;
    433     //  SkASSERT(maxStorage == 0 || maxStorage == numberOfComponents);
    434         if (maxStorage == 0)
    435             arrayStorage->setCount(numberOfComponents);
    436         for (int index = 0; index < numberOfColors; index++) {
    437             SkColor color = scriptValue.fType == SkType_Array ?
    438                 (SkColor) array->begin()[index].fS32 : (SkColor) scriptValue.fOperand.fS32;
    439             storage[0].fScalar = SkIntToScalar(SkColorGetA(color));
    440             storage[1].fScalar = SkIntToScalar(SkColorGetR(color));
    441             storage[2].fScalar = SkIntToScalar(SkColorGetG(color));
    442             storage[3].fScalar = SkIntToScalar(SkColorGetB(color));
    443             storage += 4;
    444         }
    445     } else if (SkDisplayType::IsStruct(NULL /* !!! maker*/, type)) {
    446         if (scriptValue.fType != SkType_Array)
    447             return true;    // error
    448         SkASSERT(sizeof(SkScalar) == sizeof(SkOperand)); // !!! no 64 bit pointer support yet
    449         int count = scriptValue.fOperand.fArray->count();
    450         if (count > 0) {
    451             SkASSERT(fCount == count);
    452             memcpy(storage, scriptValue.fOperand.fArray->begin(), count * sizeof(SkOperand));
    453         }
    454     } else if (scriptValue.fType == SkType_Array) {
    455         SkASSERT(scriptValue.fOperand.fArray->getType() == type);
    456         SkASSERT(scriptValue.fOperand.fArray->count() == getCount());
    457         memcpy(storage, scriptValue.fOperand.fArray->begin(), getCount() * sizeof(SkOperand));
    458     } else {
    459         memcpy(storage, &scriptValue.fOperand, sizeof(SkOperand));
    460     }
    461     return false;
    462 }
    463 
    464 
    465 //void SkMemberInfo::setValue(SkDisplayable* displayable, const char value[], const char name[]) const {
    466 //  void* valuePtr = (void*) ((char*) displayable + fOffset);
    467 //  switch (fType) {
    468 //      case SkType_Point3D: {
    469 //          static const char xyz[] = "x|y|z";
    470 //          int index = find_one(xyz, name);
    471 //          SkASSERT(index >= 0);
    472 //          valuePtr = (void*) ((char*) valuePtr + index * sizeof(SkScalar));
    473 //          } break;
    474 //      default:
    475 //          SkASSERT(0);
    476 //  }
    477 //  SkParse::FindScalar(value, (SkScalar*) valuePtr);
    478 //  displayable->dirty();
    479 //}
    480 
    481 #if SK_USE_CONDENSED_INFO == 0
    482 
    483 // Find Nth memberInfo
    484 const SkMemberInfo* SkMemberInfo::Find(const SkMemberInfo info[], int count, int* index) {
    485     SkASSERT(*index >= 0);
    486     if (info->fType == SkType_BaseClassInfo) {
    487         const SkMemberInfo* inherited = (SkMemberInfo*) info->fName;
    488         const SkMemberInfo* result = SkMemberInfo::Find(inherited, info->fCount, index);
    489         if (result != NULL)
    490             return result;
    491         if (--count == 0)
    492             return NULL;
    493         info++;
    494     }
    495     SkASSERT(info->fName);
    496     SkASSERT(info->fType != SkType_BaseClassInfo);
    497     if (*index >= count) {
    498         *index -= count;
    499         return NULL;
    500     }
    501     return &info[*index];
    502 }
    503 
    504 // Find named memberinfo
    505 const SkMemberInfo* SkMemberInfo::Find(const SkMemberInfo info[], int count, const char** matchPtr) {
    506     const char* match = *matchPtr;
    507     if (info->fType == SkType_BaseClassInfo) {
    508         const SkMemberInfo* inherited = (SkMemberInfo*) info->fName;
    509         const SkMemberInfo* result = SkMemberInfo::Find(inherited, info->fCount, matchPtr);
    510         if (result != NULL)
    511             return result;
    512         if (--count == 0)
    513             return NULL;
    514         info++;
    515     }
    516     SkASSERT(info->fName);
    517     SkASSERT(info->fType != SkType_BaseClassInfo);
    518     int index = SkStrSearch(&info->fName, count, match, sizeof(*info));
    519     if (index < 0 || index >= count)
    520         return NULL;
    521     return &info[index];
    522 }
    523 
    524 const SkMemberInfo* SkMemberInfo::getInherited() const {
    525     return (SkMemberInfo*) fName;
    526 }
    527 
    528 #endif // SK_USE_CONDENSED_INFO == 0
    529 
    530 #if 0
    531 bool SkMemberInfo::SetValue(void* valuePtr, const char value[], SkDisplayTypes type,
    532                             int count) {
    533     switch (type) {
    534         case SkType_Animate:
    535         case SkType_BaseBitmap:
    536         case SkType_Bitmap:
    537         case SkType_Dash:
    538         case SkType_Displayable:
    539         case SkType_Drawable:
    540         case SkType_Matrix:
    541         case SkType_Path:
    542         case SkType_Text:
    543         case SkType_3D_Patch:
    544             return false; // ref to object; caller must resolve
    545         case SkType_MSec: {
    546             SkParse::FindMSec(value, (SkMSec*) valuePtr);
    547             } break;
    548         case SkType_3D_Point:
    549         case SkType_Point:
    550     //  case SkType_PointArray:
    551         case SkType_ScalarArray:
    552             SkParse::FindScalars(value, (SkScalar*) valuePtr, count);
    553             break;
    554         default:
    555             SkASSERT(0);
    556     }
    557     return true;
    558 }
    559 #endif
    560