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