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