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::addChild(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 nullptr; 68 } 69 70 SkDisplayable* SkDisplayable::deepCopy(SkAnimateMaker* maker) { 71 SkDisplayTypes type = getType(); 72 if (type == SkType_Unknown) { 73 SkASSERT(0); 74 return nullptr; 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 == nullptr) 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 == nullptr || (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 == nullptr || *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 (nullptr == 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 == nullptr || (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 SkDebugf("%g", SkScalarToFloat(op->fScalar)); 209 break; 210 case SkType_String: 211 case SkType_DynamicString: 212 SkDebugf("%s", op->fString->c_str()); 213 break; 214 default: 215 break; 216 } 217 firstElem = false; 218 } 219 SkDebugf("]\" "); 220 continue; 221 } 222 223 if (info->fType == SkType_String || info->fType == SkType_DynamicString) { 224 SkString* string; 225 info->getString(this, &string); 226 if (string->isEmpty() == false) 227 SkDebugf("%s=\"%s\"\t", info->fName, string->c_str()); 228 continue; 229 } 230 231 232 blankInfo = blankCopy->getMember(index); 233 int i = info->fCount; 234 info->getValue(this, values, i); 235 blankInfo->getValue(blankCopy, blankValues, i); 236 dumpValues(info, info->fType, values[0], blankValues[0], values[1], blankValues[1]); 237 } while (true); 238 delete blankCopy; 239 } 240 241 void SkDisplayable::dumpBase(SkAnimateMaker* maker) { 242 SkDisplayTypes type = getType(); 243 const char* elementName = "(unknown)"; 244 if (type != SkType_Unknown && type != SkType_Screenplay) 245 elementName = SkDisplayType::GetName(maker, type); 246 SkDebugf("%*s", SkDisplayList::fIndent, ""); 247 if (SkDisplayList::fDumpIndex != 0 && SkDisplayList::fIndent == 0) 248 SkDebugf("%d: ", SkDisplayList::fDumpIndex); 249 SkDebugf("<%s ", elementName); 250 if (strcmp(id,"") != 0) 251 SkDebugf("id=\"%s\" ", id); 252 } 253 254 void SkDisplayable::dumpChildren(SkAnimateMaker* maker, bool closedAngle) { 255 256 int index = -1; 257 const SkMemberInfo* info; 258 index = -1; 259 SkDisplayList::fIndent += 4; 260 do { 261 info = this->getMember(++index); 262 if (nullptr == info) { 263 break; 264 } 265 if (SkDisplayType::IsDisplayable(maker, info->fType)) { 266 SkDisplayable** displayable = (SkDisplayable**) info->memberData(this); 267 if (*displayable == nullptr || *displayable == (SkDisplayable*) -1) 268 continue; 269 if (closedAngle == false) { 270 SkDebugf(">\n"); 271 closedAngle = true; 272 } 273 (*displayable)->dump(maker); 274 } 275 } while (true); 276 SkDisplayList::fIndent -= 4; 277 if (closedAngle) 278 dumpEnd(maker); 279 else 280 SkDebugf("/>\n"); 281 } 282 283 void SkDisplayable::dumpEnd(SkAnimateMaker* maker) { 284 SkDisplayTypes type = getType(); 285 const char* elementName = "(unknown)"; 286 if (type != SkType_Unknown && type != SkType_Screenplay) 287 elementName = SkDisplayType::GetName(maker, type); 288 SkDebugf("%*s", SkDisplayList::fIndent, ""); 289 SkDebugf("</%s>\n", elementName); 290 } 291 292 void SkDisplayable::dumpEvents() { 293 } 294 295 void SkDisplayable::dumpValues(const SkMemberInfo* info, SkDisplayTypes type, SkOperand op, SkOperand blankOp, 296 SkOperand op2, SkOperand blankOp2) { 297 switch (type) { 298 case SkType_BitmapEncoding: 299 switch (op.fS32) { 300 case 0 : SkDebugf("type=\"jpeg\" "); 301 break; 302 case 1 : SkDebugf("type=\"png\" "); 303 break; 304 default: SkDebugf("type=\"UNDEFINED\" "); 305 } 306 break; 307 //should make this a separate case in dump attrs, rather than make dump values have a larger signature 308 case SkType_Point: 309 if (op.fScalar != blankOp.fScalar || op2.fScalar != blankOp.fScalar) { 310 SkDebugf("%s=\"[%g,%g]\" ", info->fName, SkScalarToFloat(op.fScalar), SkScalarToFloat(op2.fScalar)); 311 } 312 break; 313 case SkType_FromPathMode: 314 switch (op.fS32) { 315 case 0: 316 //don't want to print anything for 0, just adding it to remove it from default: 317 break; 318 case 1: 319 SkDebugf("%s=\"%s\" ", info->fName, "angle"); 320 break; 321 case 2: 322 SkDebugf("%s=\"%s\" ", info->fName, "position"); 323 break; 324 default: 325 SkDebugf("%s=\"INVALID\" ", info->fName); 326 } 327 break; 328 case SkType_MaskFilterBlurStyle: 329 switch (op.fS32) { 330 case 0: 331 break; 332 case 1: 333 SkDebugf("%s=\"%s\" ", info->fName, "solid"); 334 break; 335 case 2: 336 SkDebugf("%s=\"%s\" ", info->fName, "outer"); 337 break; 338 case 3: 339 SkDebugf("%s=\"%s\" ", info->fName, "inner"); 340 break; 341 default: 342 SkDebugf("%s=\"INVALID\" ", info->fName); 343 } 344 break; 345 case SkType_FilterType: 346 if (op.fS32 == 1) 347 SkDebugf("%s=\"%s\" ", info->fName, "bilinear"); 348 break; 349 case SkType_PathDirection: 350 SkDebugf("%s=\"%s\" ", info->fName, op.fS32 == 0 ? "cw" : "ccw"); 351 break; 352 case SkType_FillType: 353 SkDebugf("%s=\"%s\" ", info->fName, op.fS32 == 0 ? "winding" : "evenOdd"); 354 break; 355 case SkType_TileMode: 356 //correct to look at the S32? 357 if (op.fS32 != blankOp.fS32) 358 SkDebugf("%s=\"%s\" ", info->fName, op.fS32 == 0 ? "clamp" : op.fS32 == 1 ? "repeat" : "mirror"); 359 break; 360 case SkType_Boolean: 361 if (op.fS32 != blankOp.fS32) 362 SkDebugf("%s=\"%s\" ", info->fName, op.fS32 == 0 ? "false" : "true"); 363 break; 364 case SkType_Int: 365 if (op.fS32 != blankOp.fS32) 366 SkDebugf(" %s=\"%d\" ", info->fName, op.fS32); 367 break; 368 case SkType_Float: 369 if (op.fScalar != blankOp.fScalar) { //or /65536? 370 SkDebugf("%s=\"%g\" ", info->fName, SkScalarToFloat(op.fScalar)); 371 } 372 break; 373 case SkType_String: 374 case SkType_DynamicString: 375 if (op.fString->size() > 0) 376 SkDebugf("%s=\"%s\" ", info->fName, op.fString->c_str()); 377 break; 378 case SkType_MSec: 379 if (op.fS32 != blankOp.fS32) { 380 SkDebugf(" %s=\"%g\" ", info->fName, op.fS32 * 0.001); 381 } 382 default: 383 SkDebugf(""); 384 } 385 } 386 387 #endif 388 389 bool SkDisplayable::enable( SkAnimateMaker& ) { 390 return false; 391 } 392 393 void SkDisplayable::enableBounder() { 394 } 395 396 void SkDisplayable::executeFunction(SkDisplayable* , int index, 397 SkTDArray<SkScriptValue>& , SkDisplayTypes, SkScriptValue* ) { 398 SkASSERT(0); 399 } 400 401 void SkDisplayable::executeFunction(SkDisplayable* target, 402 const SkMemberInfo* info, SkTypedArray* values, SkScriptValue* value) { 403 SkTDArray<SkScriptValue> typedValues; 404 for (SkOperand* op = values->begin(); op < values->end(); op++) { 405 SkScriptValue temp; 406 temp.fType = values->getType(); 407 temp.fOperand = *op; 408 *typedValues.append() = temp; 409 } 410 executeFunction(target, info->functionIndex(), typedValues, info->getType(), value); 411 } 412 413 void SkDisplayable::executeFunction2(SkDisplayable* , int index, 414 SkOpArray* params, SkDisplayTypes, SkOperand2* ) { 415 SkASSERT(0); 416 } 417 418 void SkDisplayable::getBounds(SkRect* rect) { 419 SkASSERT(rect); 420 rect->fLeft = rect->fTop = SK_ScalarMax; 421 rect->fRight= rect->fBottom = -SK_ScalarMax; 422 } 423 424 const SkFunctionParamType* SkDisplayable::getFunctionsParameters() { 425 return nullptr; 426 } 427 428 const SkMemberInfo* SkDisplayable::getMember(int index) { 429 return nullptr; 430 } 431 432 const SkMemberInfo* SkDisplayable::getMember(const char name[]) { 433 return nullptr; 434 } 435 436 const SkFunctionParamType* SkDisplayable::getParameters(const SkMemberInfo* info, 437 int* paramCount) { 438 const SkFunctionParamType* params = getFunctionsParameters(); 439 SkASSERT(params != nullptr); 440 int funcIndex = info->functionIndex(); 441 // !!! eventually break traversing params into an external function (maybe this whole function) 442 int index = funcIndex; 443 int offset = 0; 444 while (--index >= 0) { 445 while (params[offset] != 0) 446 offset++; 447 offset++; 448 } 449 int count = 0; 450 while (params[offset] != 0) { 451 count++; 452 offset++; 453 } 454 *paramCount = count; 455 return ¶ms[offset - count]; 456 } 457 458 SkDisplayable* SkDisplayable::getParent() const { 459 return nullptr; 460 } 461 462 bool SkDisplayable::getProperty(int index, SkScriptValue* ) const { 463 // SkASSERT(0); 464 return false; 465 } 466 467 bool SkDisplayable::getProperty2(int index, SkOperand2* value) const { 468 SkASSERT(0); 469 return false; 470 } 471 472 SkDisplayTypes SkDisplayable::getType() const { 473 return SkType_Unknown; 474 } 475 476 bool SkDisplayable::hasEnable() const { 477 return false; 478 } 479 480 bool SkDisplayable::isDrawable() const { 481 return false; 482 } 483 484 void SkDisplayable::onEndElement(SkAnimateMaker& ) {} 485 486 const SkMemberInfo* SkDisplayable::preferredChild(SkDisplayTypes type) { 487 return nullptr; 488 } 489 490 bool SkDisplayable::resolveIDs(SkAnimateMaker& maker, SkDisplayable* original, SkApply* apply) { 491 return false; 492 } 493 494 //SkDisplayable* SkDisplayable::resolveTarget(SkAnimateMaker& ) { 495 // return this; 496 //} 497 498 void SkDisplayable::setChildHasID() { 499 } 500 501 bool SkDisplayable::setParent(SkDisplayable* ) { 502 return false; 503 } 504 505 bool SkDisplayable::setProperty(int index, SkScriptValue& ) { 506 //SkASSERT(0); 507 return false; 508 } 509 510 void SkDisplayable::setReference(const SkMemberInfo* info, SkDisplayable* displayable) { 511 if (info->fType == SkType_MemberProperty) { 512 SkScriptValue scriptValue; 513 scriptValue.fOperand.fDisplayable = displayable; 514 scriptValue.fType = displayable->getType(); 515 setProperty(info->propertyIndex(), scriptValue); 516 } else if (info->fType == SkType_Array) { 517 SkASSERT(displayable->getType() == SkType_Array); 518 SkDisplayArray* dispArray = (SkDisplayArray*) displayable; 519 SkTDScalarArray* array = (SkTDScalarArray* ) info->memberData(this); 520 array->setCount(dispArray->values.count()); 521 memcpy(array->begin(), dispArray->values.begin(), dispArray->values.count() * sizeof(int)); 522 // 523 524 // !!! need a way for interpreter engine to own array 525 // !!! probably need to replace all scriptable arrays with single bigger array 526 // that has operand and type on every element -- or 527 // when array is dirtied, need to get parent to reparse to local array 528 } else { 529 void* storage = info->memberData(this); 530 memcpy(storage, &displayable, sizeof(SkDisplayable*)); 531 } 532 // !!! unclear why displayable is dirtied here 533 // if this is called, this breaks fromPath.xml 534 // displayable->dirty(); 535 } 536 537 #ifdef SK_DEBUG 538 void SkDisplayable::validate() { 539 } 540 #endif 541