blob: 7fae5033fd2d6693fa82edcc912f935ee41a6cd3 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
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
reed@android.com8a1c16f2008-12-17 15:59:43 +00009
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
24size_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
83bool 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();
tomhudson@google.coma7ed3cc2011-07-29 13:20:06 +000092 } else {
reed@android.com8a1c16f2008-12-17 15:59:43 +000093 SkASSERT(0); // incomplete
tomhudson@google.coma7ed3cc2011-07-29 13:20:06 +000094 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000095 size_t byteSize = GetSize(type);
96 memcpy(value, valuePtr + index * byteSize, byteSize);
97 return true;
98}
99
100size_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
124void 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
138void 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
147void SkMemberInfo::setString(SkDisplayable* displayable, SkString* value) const {
148 SkString* string = (SkString*) memberData(displayable);
149 string->set(*value);
150 displayable->dirty();
151}
152
153void 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
167static inline bool is_between(int c, int min, int max)
168{
169 return (unsigned)(c - min) <= (unsigned)(max - min);
170}
171
172static 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
183bool 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:
250scriptCommon: {
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) {
tomhudson@google.coma7ed3cc2011-07-29 13:20:06 +0000261 const char* charPtr = NULL;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000262 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 = SkScalarMulRound(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 {
336writeStruct:
337 if (writeValue(displayable, arrayStorage, storageOffset, maxStorage,
338 untypedStorage, outType, scriptValue)) {
339 maker.setErrorCode(SkDisplayXMLParserError::kUnexpectedType);
340 return false;
341 }
342 }
343dirty:
344 if (displayable)
345 displayable->dirty();
346 return true;
347}
348
349bool 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
356bool 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
484const 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
505const 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
524const SkMemberInfo* SkMemberInfo::getInherited() const {
525 return (SkMemberInfo*) fName;
526}
527
528#endif // SK_USE_CONDENSED_INFO == 0
529
530#if 0
531bool 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
561