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
SkDisplayable()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
~SkDisplayable()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
add(SkAnimateMaker &,SkDisplayable * child)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
canContainDependents() const51 bool SkDisplayable::canContainDependents() const {
52 return false;
53 }
54
childrenNeedDisposing() const55 bool SkDisplayable::childrenNeedDisposing() const {
56 return false;
57 }
58
clearBounder()59 void SkDisplayable::clearBounder() {
60 }
61
contains(SkDisplayable *)62 bool SkDisplayable::contains(SkDisplayable* ) {
63 return false;
64 }
65
contains(const SkString &)66 SkDisplayable* SkDisplayable::contains(const SkString& ) {
67 return NULL;
68 }
69
deepCopy(SkAnimateMaker * maker)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
dirty()133 void SkDisplayable::dirty() {
134 }
135
136 #ifdef SK_DUMP_ENABLED
dump(SkAnimateMaker * maker)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
dumpAttrs(SkAnimateMaker * maker)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
dumpBase(SkAnimateMaker * maker)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
dumpChildren(SkAnimateMaker * maker,bool closedAngle)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
dumpEnd(SkAnimateMaker * maker)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
dumpEvents()296 void SkDisplayable::dumpEvents() {
297 }
298
dumpValues(const SkMemberInfo * info,SkDisplayTypes type,SkOperand op,SkOperand blankOp,SkOperand op2,SkOperand blankOp2)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
enable(SkAnimateMaker &)405 bool SkDisplayable::enable( SkAnimateMaker& ) {
406 return false;
407 }
408
enableBounder()409 void SkDisplayable::enableBounder() {
410 }
411
executeFunction(SkDisplayable *,int index,SkTDArray<SkScriptValue> &,SkDisplayTypes,SkScriptValue *)412 void SkDisplayable::executeFunction(SkDisplayable* , int index,
413 SkTDArray<SkScriptValue>& , SkDisplayTypes, SkScriptValue* ) {
414 SkASSERT(0);
415 }
416
executeFunction(SkDisplayable * target,const SkMemberInfo * info,SkTypedArray * values,SkScriptValue * value)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
executeFunction2(SkDisplayable *,int index,SkOpArray * params,SkDisplayTypes,SkOperand2 *)429 void SkDisplayable::executeFunction2(SkDisplayable* , int index,
430 SkOpArray* params, SkDisplayTypes, SkOperand2* ) {
431 SkASSERT(0);
432 }
433
getBounds(SkRect * rect)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
getFunctionsParameters()440 const SkFunctionParamType* SkDisplayable::getFunctionsParameters() {
441 return NULL;
442 }
443
getMember(int index)444 const SkMemberInfo* SkDisplayable::getMember(int index) {
445 return NULL;
446 }
447
getMember(const char name[])448 const SkMemberInfo* SkDisplayable::getMember(const char name[]) {
449 return NULL;
450 }
451
getParameters(const SkMemberInfo * info,int * paramCount)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
getParent() const474 SkDisplayable* SkDisplayable::getParent() const {
475 return NULL;
476 }
477
getProperty(int index,SkScriptValue *) const478 bool SkDisplayable::getProperty(int index, SkScriptValue* ) const {
479 // SkASSERT(0);
480 return false;
481 }
482
getProperty2(int index,SkOperand2 * value) const483 bool SkDisplayable::getProperty2(int index, SkOperand2* value) const {
484 SkASSERT(0);
485 return false;
486 }
487
getType() const488 SkDisplayTypes SkDisplayable::getType() const {
489 return SkType_Unknown;
490 }
491
hasEnable() const492 bool SkDisplayable::hasEnable() const {
493 return false;
494 }
495
isDrawable() const496 bool SkDisplayable::isDrawable() const {
497 return false;
498 }
499
onEndElement(SkAnimateMaker &)500 void SkDisplayable::onEndElement(SkAnimateMaker& ) {}
501
preferredChild(SkDisplayTypes type)502 const SkMemberInfo* SkDisplayable::preferredChild(SkDisplayTypes type) {
503 return NULL;
504 }
505
resolveIDs(SkAnimateMaker & maker,SkDisplayable * original,SkApply * apply)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
setChildHasID()514 void SkDisplayable::setChildHasID() {
515 }
516
setParent(SkDisplayable *)517 bool SkDisplayable::setParent(SkDisplayable* ) {
518 return false;
519 }
520
setProperty(int index,SkScriptValue &)521 bool SkDisplayable::setProperty(int index, SkScriptValue& ) {
522 //SkASSERT(0);
523 return false;
524 }
525
setReference(const SkMemberInfo * info,SkDisplayable * displayable)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
validate()554 void SkDisplayable::validate() {
555 }
556 #endif
557
558
559