blob: 50536c264079fcebd1f891d5b7bd1efc4754b5d9 [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001/* 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
32size_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
91bool 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
107size_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
131void 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
145void 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
154void SkMemberInfo::setString(SkDisplayable* displayable, SkString* value) const {
155 SkString* string = (SkString*) memberData(displayable);
156 string->set(*value);
157 displayable->dirty();
158}
159
160void 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
174static inline bool is_between(int c, int min, int max)
175{
176 return (unsigned)(c - min) <= (unsigned)(max - min);
177}
178
179static 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
190bool 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:
257scriptCommon: {
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 {
343writeStruct:
344 if (writeValue(displayable, arrayStorage, storageOffset, maxStorage,
345 untypedStorage, outType, scriptValue)) {
346 maker.setErrorCode(SkDisplayXMLParserError::kUnexpectedType);
347 return false;
348 }
349 }
350dirty:
351 if (displayable)
352 displayable->dirty();
353 return true;
354}
355
356bool 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
363bool 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
491const 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
512const 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
531const SkMemberInfo* SkMemberInfo::getInherited() const {
532 return (SkMemberInfo*) fName;
533}
534
535#endif // SK_USE_CONDENSED_INFO == 0
536
537#if 0
538bool 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