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
SkDisplayable()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
~SkDisplayable()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
add(SkAnimateMaker &,SkDisplayable * child)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
canContainDependents() const59 bool SkDisplayable::canContainDependents() const {
60 return false;
61 }
62
childrenNeedDisposing() const63 bool SkDisplayable::childrenNeedDisposing() const {
64 return false;
65 }
66
clearBounder()67 void SkDisplayable::clearBounder() {
68 }
69
contains(SkDisplayable *)70 bool SkDisplayable::contains(SkDisplayable* ) {
71 return false;
72 }
73
contains(const SkString &)74 SkDisplayable* SkDisplayable::contains(const SkString& ) {
75 return NULL;
76 }
77
deepCopy(SkAnimateMaker * maker)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
dirty()141 void SkDisplayable::dirty() {
142 }
143
144 #ifdef SK_DUMP_ENABLED
dump(SkAnimateMaker * maker)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
dumpAttrs(SkAnimateMaker * maker)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
dumpBase(SkAnimateMaker * maker)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
dumpChildren(SkAnimateMaker * maker,bool closedAngle)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
dumpEnd(SkAnimateMaker * maker)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
dumpEvents()304 void SkDisplayable::dumpEvents() {
305 }
306
dumpValues(const SkMemberInfo * info,SkDisplayTypes type,SkOperand op,SkOperand blankOp,SkOperand op2,SkOperand blankOp2)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
enable(SkAnimateMaker &)413 bool SkDisplayable::enable( SkAnimateMaker& ) {
414 return false;
415 }
416
enableBounder()417 void SkDisplayable::enableBounder() {
418 }
419
executeFunction(SkDisplayable *,int index,SkTDArray<SkScriptValue> &,SkDisplayTypes,SkScriptValue *)420 void SkDisplayable::executeFunction(SkDisplayable* , int index,
421 SkTDArray<SkScriptValue>& , SkDisplayTypes, SkScriptValue* ) {
422 SkASSERT(0);
423 }
424
executeFunction(SkDisplayable * target,const SkMemberInfo * info,SkTypedArray * values,SkScriptValue * value)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
executeFunction2(SkDisplayable *,int index,SkOpArray * params,SkDisplayTypes,SkOperand2 *)437 void SkDisplayable::executeFunction2(SkDisplayable* , int index,
438 SkOpArray* params, SkDisplayTypes, SkOperand2* ) {
439 SkASSERT(0);
440 }
441
getBounds(SkRect * rect)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
getFunctionsParameters()448 const SkFunctionParamType* SkDisplayable::getFunctionsParameters() {
449 return NULL;
450 }
451
getMember(int index)452 const SkMemberInfo* SkDisplayable::getMember(int index) {
453 return NULL;
454 }
455
getMember(const char name[])456 const SkMemberInfo* SkDisplayable::getMember(const char name[]) {
457 return NULL;
458 }
459
getParameters(const SkMemberInfo * info,int * paramCount)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
getParent() const482 SkDisplayable* SkDisplayable::getParent() const {
483 return NULL;
484 }
485
getProperty(int index,SkScriptValue *) const486 bool SkDisplayable::getProperty(int index, SkScriptValue* ) const {
487 // SkASSERT(0);
488 return false;
489 }
490
getProperty2(int index,SkOperand2 * value) const491 bool SkDisplayable::getProperty2(int index, SkOperand2* value) const {
492 SkASSERT(0);
493 return false;
494 }
495
getType() const496 SkDisplayTypes SkDisplayable::getType() const {
497 return SkType_Unknown;
498 }
499
hasEnable() const500 bool SkDisplayable::hasEnable() const {
501 return false;
502 }
503
isDrawable() const504 bool SkDisplayable::isDrawable() const {
505 return false;
506 }
507
onEndElement(SkAnimateMaker &)508 void SkDisplayable::onEndElement(SkAnimateMaker& ) {}
509
preferredChild(SkDisplayTypes type)510 const SkMemberInfo* SkDisplayable::preferredChild(SkDisplayTypes type) {
511 return NULL;
512 }
513
resolveIDs(SkAnimateMaker & maker,SkDisplayable * original,SkApply * apply)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
setChildHasID()522 void SkDisplayable::setChildHasID() {
523 }
524
setParent(SkDisplayable *)525 bool SkDisplayable::setParent(SkDisplayable* ) {
526 return false;
527 }
528
setProperty(int index,SkScriptValue &)529 bool SkDisplayable::setProperty(int index, SkScriptValue& ) {
530 //SkASSERT(0);
531 return false;
532 }
533
setReference(const SkMemberInfo * info,SkDisplayable * displayable)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
validate()562 void SkDisplayable::validate() {
563 }
564 #endif
565
566
567