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 
GetSize(SkDisplayTypes type)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 
getArrayValue(const SkDisplayable * displayable,int index,SkOperand * value) const83 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 
getSize(const SkDisplayable * displayable) const100 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 
getString(const SkDisplayable * displayable,SkString ** string) const124 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 
getValue(const SkDisplayable * displayable,SkOperand value[],int count) const138 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 
setString(SkDisplayable * displayable,SkString * value) const147 void SkMemberInfo::setString(SkDisplayable* displayable, SkString* value) const {
148     SkString* string = (SkString*) memberData(displayable);
149     string->set(*value);
150     displayable->dirty();
151 }
152 
setValue(SkDisplayable * displayable,const SkOperand values[],int count) const153 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 
is_between(int c,int min,int max)167 static inline bool is_between(int c, int min, int max)
168 {
169     return (unsigned)(c - min) <= (unsigned)(max - min);
170 }
171 
is_hex(int c)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 
setValue(SkAnimateMaker & maker,SkTDOperandArray * arrayStorage,int storageOffset,int maxStorage,SkDisplayable * displayable,SkDisplayTypes outType,const char rawValue[],size_t rawValueLen) const183 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 
setValue(SkAnimateMaker & maker,SkTDOperandArray * arrayStorage,int storageOffset,int maxStorage,SkDisplayable * displayable,SkDisplayTypes outType,SkString & raw) const349 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 
writeValue(SkDisplayable * displayable,SkTDOperandArray * arrayStorage,int storageOffset,int maxStorage,void * untypedStorage,SkDisplayTypes outType,SkScriptValue & scriptValue) const356 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
Find(const SkMemberInfo info[],int count,int * index)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
Find(const SkMemberInfo info[],int count,const char ** matchPtr)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 
getInherited() const524 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