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 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 83 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 100 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 124 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 138 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 147 void SkMemberInfo::setString(SkDisplayable* displayable, SkString* value) const { 148 SkString* string = (SkString*) memberData(displayable); 149 string->set(*value); 150 displayable->dirty(); 151 } 152 153 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 167 static inline bool is_between(int c, int min, int max) 168 { 169 return (unsigned)(c - min) <= (unsigned)(max - min); 170 } 171 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 183 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 349 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 356 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 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 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 524 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