• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
GetSize(SkDisplayTypes type)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 
getArrayValue(const SkDisplayable * displayable,int index,SkOperand * value) const91 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 
getSize(const SkDisplayable * displayable) const107 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 
getString(const SkDisplayable * displayable,SkString ** string) const131 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 
getValue(const SkDisplayable * displayable,SkOperand value[],int count) const145 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 
setString(SkDisplayable * displayable,SkString * value) const154 void SkMemberInfo::setString(SkDisplayable* displayable, SkString* value) const {
155     SkString* string = (SkString*) memberData(displayable);
156     string->set(*value);
157     displayable->dirty();
158 }
159 
setValue(SkDisplayable * displayable,const SkOperand values[],int count) const160 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 
is_between(int c,int min,int max)174 static inline bool is_between(int c, int min, int max)
175 {
176     return (unsigned)(c - min) <= (unsigned)(max - min);
177 }
178 
is_hex(int c)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 
setValue(SkAnimateMaker & maker,SkTDOperandArray * arrayStorage,int storageOffset,int maxStorage,SkDisplayable * displayable,SkDisplayTypes outType,const char rawValue[],size_t rawValueLen) const190 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 
setValue(SkAnimateMaker & maker,SkTDOperandArray * arrayStorage,int storageOffset,int maxStorage,SkDisplayable * displayable,SkDisplayTypes outType,SkString & raw) const356 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 
writeValue(SkDisplayable * displayable,SkTDOperandArray * arrayStorage,int storageOffset,int maxStorage,void * untypedStorage,SkDisplayTypes outType,SkScriptValue & scriptValue) const363 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
Find(const SkMemberInfo info[],int count,int * index)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
Find(const SkMemberInfo info[],int count,const char ** matchPtr)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 
getInherited() const531 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