1 /* libs/graphics/animator/SkDisplayable.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 "SkDisplayable.h" 19 #include "SkDisplayApply.h" 20 #include "SkParse.h" 21 #ifdef SK_DEBUG 22 #include "SkDisplayList.h" 23 #endif 24 #include "SkDisplayTypes.h" 25 26 #ifdef SK_FIND_LEAKS 27 // int SkDisplayable::fAllocationCount; 28 SkTDDisplayableArray SkDisplayable::fAllocations; 29 #endif 30 31 #ifdef SK_DEBUG 32 SkDisplayable::SkDisplayable() { 33 id = _id.c_str(); 34 #ifdef SK_FIND_LEAKS 35 // fAllocationCount++; 36 *fAllocations.append() = this; 37 #endif 38 } 39 #endif 40 41 SkDisplayable::~SkDisplayable() { 42 #ifdef SK_FIND_LEAKS 43 // fAllocationCount--; 44 int index = fAllocations.find(this); 45 SkASSERT(index >= 0); 46 fAllocations.remove(index); 47 #endif 48 } 49 50 bool SkDisplayable::add(SkAnimateMaker& , SkDisplayable* child) { 51 return false; 52 } 53 54 //void SkDisplayable::apply(SkAnimateMaker& , const SkMemberInfo* , 55 // SkDisplayable* , SkScalar [], int count) { 56 // SkASSERT(0); 57 //} 58 59 bool SkDisplayable::canContainDependents() const { 60 return false; 61 } 62 63 bool SkDisplayable::childrenNeedDisposing() const { 64 return false; 65 } 66 67 void SkDisplayable::clearBounder() { 68 } 69 70 bool SkDisplayable::contains(SkDisplayable* ) { 71 return false; 72 } 73 74 SkDisplayable* SkDisplayable::contains(const SkString& ) { 75 return NULL; 76 } 77 78 SkDisplayable* SkDisplayable::deepCopy(SkAnimateMaker* maker) { 79 SkDisplayTypes type = getType(); 80 if (type == SkType_Unknown) { 81 SkASSERT(0); 82 return NULL; 83 } 84 SkDisplayable* copy = SkDisplayType::CreateInstance(maker, type); 85 int index = -1; 86 int propIndex = 0; 87 const SkMemberInfo* info; 88 do { 89 info = copy->getMember(++index); 90 if (info == NULL) 91 break; 92 if (info->fType == SkType_MemberProperty) { 93 SkScriptValue value; 94 if (getProperty(propIndex, &value)) 95 copy->setProperty(propIndex, value); 96 propIndex++; 97 continue; 98 } 99 if (info->fType == SkType_MemberFunction) 100 continue; 101 if (info->fType == SkType_Array) { 102 SkTDOperandArray* array = (SkTDOperandArray*) info->memberData(this); 103 int arrayCount; 104 if (array == NULL || (arrayCount = array->count()) == 0) 105 continue; 106 SkTDOperandArray* copyArray = (SkTDOperandArray*) info->memberData(copy); 107 copyArray->setCount(arrayCount); 108 SkDisplayTypes elementType; 109 if (type == SkType_Array) { 110 SkDisplayArray* dispArray = (SkDisplayArray*) this; 111 elementType = dispArray->values.getType(); 112 } else 113 elementType = info->arrayType(); 114 size_t elementSize = SkMemberInfo::GetSize(elementType); 115 size_t byteSize = elementSize * arrayCount; 116 memcpy(copyArray->begin(), array->begin(), byteSize); 117 continue; 118 } 119 if (SkDisplayType::IsDisplayable(maker, info->fType)) { 120 SkDisplayable** displayable = (SkDisplayable**) info->memberData(this); 121 if (*displayable == NULL || *displayable == (SkDisplayable*) -1) 122 continue; 123 SkDisplayable* deeper = (*displayable)->deepCopy(maker); 124 info->setMemberData(copy, deeper, sizeof(deeper)); 125 continue; 126 } 127 if (info->fType == SkType_String || info->fType == SkType_DynamicString) { 128 SkString* string; 129 info->getString(this, &string); 130 info->setString(copy, string); 131 continue; 132 } 133 void* data = info->memberData(this); 134 size_t size = SkMemberInfo::GetSize(info->fType); 135 info->setMemberData(copy, data, size); 136 } while (true); 137 copy->dirty(); 138 return copy; 139 } 140 141 void SkDisplayable::dirty() { 142 } 143 144 #ifdef SK_DUMP_ENABLED 145 void SkDisplayable::dump(SkAnimateMaker* maker) { 146 dumpBase(maker); 147 #if SK_USE_CONDENSED_INFO == 0 148 this->dumpAttrs(maker); 149 this->dumpChildren(maker); 150 #endif 151 } 152 153 void SkDisplayable::dumpAttrs(SkAnimateMaker* maker) { 154 SkDisplayTypes type = getType(); 155 if (type == SkType_Unknown) { 156 //SkDebugf("/>\n"); 157 return; 158 } 159 SkDisplayable* blankCopy = SkDisplayType::CreateInstance(maker, type); 160 161 int index = -1; 162 int propIndex = 0; 163 const SkMemberInfo* info; 164 const SkMemberInfo* blankInfo; 165 SkScriptValue value; 166 SkScriptValue blankValue; 167 SkOperand values[2]; 168 SkOperand blankValues[2]; 169 do { 170 info = this->getMember(++index); 171 if (NULL == info) { 172 //SkDebugf("\n"); 173 break; 174 } 175 if (SkType_MemberProperty == info->fType) { 176 if (getProperty(propIndex, &value)) { 177 blankCopy->getProperty(propIndex, &blankValue); 178 //last two are dummies 179 dumpValues(info, value.fType, value.fOperand, blankValue.fOperand, value.fOperand, blankValue.fOperand); 180 } 181 182 propIndex++; 183 continue; 184 } 185 if (SkDisplayType::IsDisplayable(maker, info->fType)) { 186 continue; 187 } 188 189 if (info->fType == SkType_MemberFunction) 190 continue; 191 192 193 if (info->fType == SkType_Array) { 194 SkTDOperandArray* array = (SkTDOperandArray*) info->memberData(this); 195 int arrayCount; 196 if (array == NULL || (arrayCount = array->count()) == 0) 197 continue; 198 SkDisplayTypes elementType; 199 if (type == SkType_Array) { 200 SkDisplayArray* dispArray = (SkDisplayArray*) this; 201 elementType = dispArray->values.getType(); 202 } else 203 elementType = info->arrayType(); 204 bool firstElem = true; 205 SkDebugf("%s=\"[", info->fName); 206 for (SkOperand* op = array->begin(); op < array->end(); op++) { 207 if (!firstElem) SkDebugf(","); 208 switch (elementType) { 209 case SkType_Displayable: 210 SkDebugf("%s", op->fDisplayable->id); 211 break; 212 case SkType_Int: 213 SkDebugf("%d", op->fS32); 214 break; 215 case SkType_Float: 216 #ifdef SK_CAN_USE_FLOAT 217 SkDebugf("%g", SkScalarToFloat(op->fScalar)); 218 #else 219 SkDebugf("%x", op->fScalar); 220 #endif 221 break; 222 case SkType_String: 223 case SkType_DynamicString: 224 SkDebugf("%s", op->fString->c_str()); 225 break; 226 default: 227 break; 228 } 229 firstElem = false; 230 } 231 SkDebugf("]\" "); 232 continue; 233 } 234 235 if (info->fType == SkType_String || info->fType == SkType_DynamicString) { 236 SkString* string; 237 info->getString(this, &string); 238 if (string->isEmpty() == false) 239 SkDebugf("%s=\"%s\"\t", info->fName, string->c_str()); 240 continue; 241 } 242 243 244 blankInfo = blankCopy->getMember(index); 245 int i = info->fCount; 246 info->getValue(this, values, i); 247 blankInfo->getValue(blankCopy, blankValues, i); 248 dumpValues(info, info->fType, values[0], blankValues[0], values[1], blankValues[1]); 249 } while (true); 250 delete blankCopy; 251 } 252 253 void SkDisplayable::dumpBase(SkAnimateMaker* maker) { 254 SkDisplayTypes type = getType(); 255 const char* elementName = "(unknown)"; 256 if (type != SkType_Unknown && type != SkType_Screenplay) 257 elementName = SkDisplayType::GetName(maker, type); 258 SkDebugf("%*s", SkDisplayList::fIndent, ""); 259 if (SkDisplayList::fDumpIndex != 0 && SkDisplayList::fIndent == 0) 260 SkDebugf("%d: ", SkDisplayList::fDumpIndex); 261 SkDebugf("<%s ", elementName); 262 if (strcmp(id,"") != 0) 263 SkDebugf("id=\"%s\" ", id); 264 } 265 266 void SkDisplayable::dumpChildren(SkAnimateMaker* maker, bool closedAngle) { 267 268 int index = -1; 269 const SkMemberInfo* info; 270 index = -1; 271 SkDisplayList::fIndent += 4; 272 do { 273 info = this->getMember(++index); 274 if (NULL == info) { 275 break; 276 } 277 if (SkDisplayType::IsDisplayable(maker, info->fType)) { 278 SkDisplayable** displayable = (SkDisplayable**) info->memberData(this); 279 if (*displayable == NULL || *displayable == (SkDisplayable*) -1) 280 continue; 281 if (closedAngle == false) { 282 SkDebugf(">\n"); 283 closedAngle = true; 284 } 285 (*displayable)->dump(maker); 286 } 287 } while (true); 288 SkDisplayList::fIndent -= 4; 289 if (closedAngle) 290 dumpEnd(maker); 291 else 292 SkDebugf("/>\n"); 293 } 294 295 void SkDisplayable::dumpEnd(SkAnimateMaker* maker) { 296 SkDisplayTypes type = getType(); 297 const char* elementName = "(unknown)"; 298 if (type != SkType_Unknown && type != SkType_Screenplay) 299 elementName = SkDisplayType::GetName(maker, type); 300 SkDebugf("%*s", SkDisplayList::fIndent, ""); 301 SkDebugf("</%s>\n", elementName); 302 } 303 304 void SkDisplayable::dumpEvents() { 305 } 306 307 void SkDisplayable::dumpValues(const SkMemberInfo* info, SkDisplayTypes type, SkOperand op, SkOperand blankOp, 308 SkOperand op2, SkOperand blankOp2) { 309 switch (type) { 310 case SkType_BitmapEncoding: 311 switch (op.fS32) { 312 case 0 : SkDebugf("type=\"jpeg\" "); 313 break; 314 case 1 : SkDebugf("type=\"png\" "); 315 break; 316 default: SkDebugf("type=\"UNDEFINED\" "); 317 } 318 break; 319 //should make this a separate case in dump attrs, rather than make dump values have a larger signature 320 case SkType_Point: 321 if (op.fScalar != blankOp.fScalar || op2.fScalar != blankOp.fScalar) { 322 #ifdef SK_CAN_USE_FLOAT 323 SkDebugf("%s=\"[%g,%g]\" ", info->fName, SkScalarToFloat(op.fScalar), SkScalarToFloat(op2.fScalar)); 324 #else 325 SkDebugf("%s=\"[%x,%x]\" ", info->fName, op.fScalar, op2.fScalar); 326 #endif 327 } 328 break; 329 case SkType_FromPathMode: 330 switch (op.fS32) { 331 case 0: 332 //don't want to print anything for 0, just adding it to remove it from default: 333 break; 334 case 1: 335 SkDebugf("%s=\"%s\" ", info->fName, "angle"); 336 break; 337 case 2: 338 SkDebugf("%s=\"%s\" ", info->fName, "position"); 339 break; 340 default: 341 SkDebugf("%s=\"INVALID\" ", info->fName); 342 } 343 break; 344 case SkType_MaskFilterBlurStyle: 345 switch (op.fS32) { 346 case 0: 347 break; 348 case 1: 349 SkDebugf("%s=\"%s\" ", info->fName, "solid"); 350 break; 351 case 2: 352 SkDebugf("%s=\"%s\" ", info->fName, "outer"); 353 break; 354 case 3: 355 SkDebugf("%s=\"%s\" ", info->fName, "inner"); 356 break; 357 default: 358 SkDebugf("%s=\"INVALID\" ", info->fName); 359 } 360 break; 361 case SkType_FilterType: 362 if (op.fS32 == 1) 363 SkDebugf("%s=\"%s\" ", info->fName, "bilinear"); 364 break; 365 case SkType_PathDirection: 366 SkDebugf("%s=\"%s\" ", info->fName, op.fS32 == 0 ? "cw" : "ccw"); 367 break; 368 case SkType_FillType: 369 SkDebugf("%s=\"%s\" ", info->fName, op.fS32 == 0 ? "winding" : "evenOdd"); 370 break; 371 case SkType_TileMode: 372 //correct to look at the S32? 373 if (op.fS32 != blankOp.fS32) 374 SkDebugf("%s=\"%s\" ", info->fName, op.fS32 == 0 ? "clamp" : op.fS32 == 1 ? "repeat" : "mirror"); 375 break; 376 case SkType_Boolean: 377 if (op.fS32 != blankOp.fS32) 378 SkDebugf("%s=\"%s\" ", info->fName, op.fS32 == 0 ? "false" : "true"); 379 break; 380 case SkType_Int: 381 if (op.fS32 != blankOp.fS32) 382 SkDebugf(" %s=\"%d\" ", info->fName, op.fS32); 383 break; 384 case SkType_Float: 385 if (op.fScalar != blankOp.fScalar) { //or /65536? 386 #ifdef SK_CAN_USE_FLOAT 387 SkDebugf("%s=\"%g\" ", info->fName, SkScalarToFloat(op.fScalar)); 388 #else 389 SkDebugf("%s=\"%x\" ", info->fName, op.fScalar); 390 #endif 391 } 392 break; 393 case SkType_String: 394 case SkType_DynamicString: 395 if (op.fString->size() > 0) 396 SkDebugf("%s=\"%s\" ", info->fName, op.fString->c_str()); 397 break; 398 case SkType_MSec: 399 if (op.fS32 != blankOp.fS32) { 400 #ifdef SK_CAN_USE_FLOAT 401 SkDebugf(" %s=\"%g\" ", info->fName, SkScalarToFloat(SkScalarDiv(op.fS32, 1000))); 402 #else 403 SkDebugf(" %s=\"%x\" ", info->fName, SkScalarDiv(op.fS32, 1000)); 404 #endif 405 } 406 default: 407 SkDebugf(""); 408 } 409 } 410 411 #endif 412 413 bool SkDisplayable::enable( SkAnimateMaker& ) { 414 return false; 415 } 416 417 void SkDisplayable::enableBounder() { 418 } 419 420 void SkDisplayable::executeFunction(SkDisplayable* , int index, 421 SkTDArray<SkScriptValue>& , SkDisplayTypes, SkScriptValue* ) { 422 SkASSERT(0); 423 } 424 425 void SkDisplayable::executeFunction(SkDisplayable* target, 426 const SkMemberInfo* info, SkTypedArray* values, SkScriptValue* value) { 427 SkTDArray<SkScriptValue> typedValues; 428 for (SkOperand* op = values->begin(); op < values->end(); op++) { 429 SkScriptValue temp; 430 temp.fType = values->getType(); 431 temp.fOperand = *op; 432 *typedValues.append() = temp; 433 } 434 executeFunction(target, info->functionIndex(), typedValues, info->getType(), value); 435 } 436 437 void SkDisplayable::executeFunction2(SkDisplayable* , int index, 438 SkOpArray* params, SkDisplayTypes, SkOperand2* ) { 439 SkASSERT(0); 440 } 441 442 void SkDisplayable::getBounds(SkRect* rect) { 443 SkASSERT(rect); 444 rect->fLeft = rect->fTop = SK_ScalarMax; 445 rect->fRight= rect->fBottom = -SK_ScalarMax; 446 } 447 448 const SkFunctionParamType* SkDisplayable::getFunctionsParameters() { 449 return NULL; 450 } 451 452 const SkMemberInfo* SkDisplayable::getMember(int index) { 453 return NULL; 454 } 455 456 const SkMemberInfo* SkDisplayable::getMember(const char name[]) { 457 return NULL; 458 } 459 460 const SkFunctionParamType* SkDisplayable::getParameters(const SkMemberInfo* info, 461 int* paramCount) { 462 const SkFunctionParamType* params = getFunctionsParameters(); 463 SkASSERT(params != NULL); 464 int funcIndex = info->functionIndex(); 465 // !!! eventually break traversing params into an external function (maybe this whole function) 466 int index = funcIndex; 467 int offset = 0; 468 while (--index >= 0) { 469 while (params[offset] != 0) 470 offset++; 471 offset++; 472 } 473 int count = 0; 474 while (params[offset] != 0) { 475 count++; 476 offset++; 477 } 478 *paramCount = count; 479 return ¶ms[offset - count]; 480 } 481 482 SkDisplayable* SkDisplayable::getParent() const { 483 return NULL; 484 } 485 486 bool SkDisplayable::getProperty(int index, SkScriptValue* ) const { 487 // SkASSERT(0); 488 return false; 489 } 490 491 bool SkDisplayable::getProperty2(int index, SkOperand2* value) const { 492 SkASSERT(0); 493 return false; 494 } 495 496 SkDisplayTypes SkDisplayable::getType() const { 497 return SkType_Unknown; 498 } 499 500 bool SkDisplayable::hasEnable() const { 501 return false; 502 } 503 504 bool SkDisplayable::isDrawable() const { 505 return false; 506 } 507 508 void SkDisplayable::onEndElement(SkAnimateMaker& ) {} 509 510 const SkMemberInfo* SkDisplayable::preferredChild(SkDisplayTypes type) { 511 return NULL; 512 } 513 514 bool SkDisplayable::resolveIDs(SkAnimateMaker& maker, SkDisplayable* original, SkApply* apply) { 515 return false; 516 } 517 518 //SkDisplayable* SkDisplayable::resolveTarget(SkAnimateMaker& ) { 519 // return this; 520 //} 521 522 void SkDisplayable::setChildHasID() { 523 } 524 525 bool SkDisplayable::setParent(SkDisplayable* ) { 526 return false; 527 } 528 529 bool SkDisplayable::setProperty(int index, SkScriptValue& ) { 530 //SkASSERT(0); 531 return false; 532 } 533 534 void SkDisplayable::setReference(const SkMemberInfo* info, SkDisplayable* displayable) { 535 if (info->fType == SkType_MemberProperty) { 536 SkScriptValue scriptValue; 537 scriptValue.fOperand.fDisplayable = displayable; 538 scriptValue.fType = displayable->getType(); 539 setProperty(info->propertyIndex(), scriptValue); 540 } else if (info->fType == SkType_Array) { 541 SkASSERT(displayable->getType() == SkType_Array); 542 SkDisplayArray* dispArray = (SkDisplayArray*) displayable; 543 SkTDScalarArray* array = (SkTDScalarArray* ) info->memberData(this); 544 array->setCount(dispArray->values.count()); 545 memcpy(array->begin(), dispArray->values.begin(), dispArray->values.count() * sizeof(int)); 546 // 547 548 // !!! need a way for interpreter engine to own array 549 // !!! probably need to replace all scriptable arrays with single bigger array 550 // that has operand and type on every element -- or 551 // when array is dirtied, need to get parent to reparse to local array 552 } else { 553 void* storage = info->memberData(this); 554 memcpy(storage, &displayable, sizeof(SkDisplayable*)); 555 } 556 // !!! unclear why displayable is dirtied here 557 // if this is called, this breaks fromPath.xml 558 // displayable->dirty(); 559 } 560 561 #ifdef SK_DEBUG 562 void SkDisplayable::validate() { 563 } 564 #endif 565 566 567