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