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