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 
addChild(SkAnimateMaker &,SkDisplayable * child)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 
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 nullptr;
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 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 
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 (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 
dumpBase(SkAnimateMaker * maker)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 
dumpChildren(SkAnimateMaker * maker,bool closedAngle)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 
dumpEnd(SkAnimateMaker * maker)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 
dumpEvents()292 void SkDisplayable::dumpEvents() {
293 }
294 
dumpValues(const SkMemberInfo * info,SkDisplayTypes type,SkOperand op,SkOperand blankOp,SkOperand op2,SkOperand blankOp2)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 
enable(SkAnimateMaker &)389 bool SkDisplayable::enable( SkAnimateMaker& ) {
390     return false;
391 }
392 
enableBounder()393 void SkDisplayable::enableBounder() {
394 }
395 
executeFunction(SkDisplayable *,int index,SkTDArray<SkScriptValue> &,SkDisplayTypes,SkScriptValue *)396 void SkDisplayable::executeFunction(SkDisplayable* , int index,
397         SkTDArray<SkScriptValue>& , SkDisplayTypes, SkScriptValue*  ) {
398     SkASSERT(0);
399 }
400 
executeFunction(SkDisplayable * target,const SkMemberInfo * info,SkTypedArray * values,SkScriptValue * value)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 
executeFunction2(SkDisplayable *,int index,SkOpArray * params,SkDisplayTypes,SkOperand2 *)413 void SkDisplayable::executeFunction2(SkDisplayable* , int index,
414         SkOpArray* params, SkDisplayTypes, SkOperand2*  ) {
415     SkASSERT(0);
416 }
417 
getBounds(SkRect * rect)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 
getFunctionsParameters()424 const SkFunctionParamType* SkDisplayable::getFunctionsParameters() {
425     return nullptr;
426 }
427 
getMember(int index)428 const SkMemberInfo* SkDisplayable::getMember(int index) {
429     return nullptr;
430 }
431 
getMember(const char name[])432 const SkMemberInfo* SkDisplayable::getMember(const char name[]) {
433     return nullptr;
434 }
435 
getParameters(const SkMemberInfo * info,int * paramCount)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 &params[offset - count];
456 }
457 
getParent() const458 SkDisplayable* SkDisplayable::getParent() const {
459     return nullptr;
460 }
461 
getProperty(int index,SkScriptValue *) const462 bool SkDisplayable::getProperty(int index, SkScriptValue* ) const {
463 //  SkASSERT(0);
464     return false;
465 }
466 
getProperty2(int index,SkOperand2 * value) const467 bool SkDisplayable::getProperty2(int index, SkOperand2* value) const {
468     SkASSERT(0);
469     return false;
470 }
471 
getType() const472 SkDisplayTypes SkDisplayable::getType() const {
473     return SkType_Unknown;
474 }
475 
hasEnable() const476 bool SkDisplayable::hasEnable() const {
477     return false;
478 }
479 
isDrawable() const480 bool SkDisplayable::isDrawable() const {
481     return false;
482 }
483 
onEndElement(SkAnimateMaker &)484 void SkDisplayable::onEndElement(SkAnimateMaker& ) {}
485 
preferredChild(SkDisplayTypes type)486 const SkMemberInfo* SkDisplayable::preferredChild(SkDisplayTypes type) {
487     return nullptr;
488 }
489 
resolveIDs(SkAnimateMaker & maker,SkDisplayable * original,SkApply * apply)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 
setChildHasID()498 void SkDisplayable::setChildHasID() {
499 }
500 
setParent(SkDisplayable *)501 bool SkDisplayable::setParent(SkDisplayable* ) {
502     return false;
503 }
504 
setProperty(int index,SkScriptValue &)505 bool SkDisplayable::setProperty(int index, SkScriptValue& ) {
506     //SkASSERT(0);
507     return false;
508 }
509 
setReference(const SkMemberInfo * info,SkDisplayable * displayable)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
validate()538 void SkDisplayable::validate() {
539 }
540 #endif
541