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;
20SkTDDisplayableArray SkDisplayable::fAllocations;
21#endif
22
23#ifdef SK_DEBUG
24SkDisplayable::SkDisplayable() {
25    id = _id.c_str();
26#ifdef SK_FIND_LEAKS
27    // fAllocationCount++;
28    *fAllocations.append() = this;
29#endif
30}
31#endif
32
33SkDisplayable::~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
42bool 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
51bool SkDisplayable::canContainDependents() const {
52    return false;
53}
54
55bool SkDisplayable::childrenNeedDisposing() const {
56    return false;
57}
58
59void SkDisplayable::clearBounder() {
60}
61
62bool SkDisplayable::contains(SkDisplayable* ) {
63    return false;
64}
65
66SkDisplayable* SkDisplayable::contains(const SkString& ) {
67    return NULL;
68}
69
70SkDisplayable* 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
133void SkDisplayable::dirty() {
134}
135
136#ifdef SK_DUMP_ENABLED
137void 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
145void 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
245void 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
258void 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
287void 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
296void SkDisplayable::dumpEvents() {
297}
298
299void 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
405bool SkDisplayable::enable( SkAnimateMaker& ) {
406    return false;
407}
408
409void SkDisplayable::enableBounder() {
410}
411
412void SkDisplayable::executeFunction(SkDisplayable* , int index,
413        SkTDArray<SkScriptValue>& , SkDisplayTypes, SkScriptValue*  ) {
414    SkASSERT(0);
415}
416
417void 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
429void SkDisplayable::executeFunction2(SkDisplayable* , int index,
430        SkOpArray* params, SkDisplayTypes, SkOperand2*  ) {
431    SkASSERT(0);
432}
433
434void SkDisplayable::getBounds(SkRect* rect) {
435    SkASSERT(rect);
436    rect->fLeft = rect->fTop = SK_ScalarMax;
437    rect->fRight= rect->fBottom = -SK_ScalarMax;
438}
439
440const SkFunctionParamType* SkDisplayable::getFunctionsParameters() {
441    return NULL;
442}
443
444const SkMemberInfo* SkDisplayable::getMember(int index) {
445    return NULL;
446}
447
448const SkMemberInfo* SkDisplayable::getMember(const char name[]) {
449    return NULL;
450}
451
452const 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 &params[offset - count];
472}
473
474SkDisplayable* SkDisplayable::getParent() const {
475    return NULL;
476}
477
478bool SkDisplayable::getProperty(int index, SkScriptValue* ) const {
479//  SkASSERT(0);
480    return false;
481}
482
483bool SkDisplayable::getProperty2(int index, SkOperand2* value) const {
484    SkASSERT(0);
485    return false;
486}
487
488SkDisplayTypes SkDisplayable::getType() const {
489    return SkType_Unknown;
490}
491
492bool SkDisplayable::hasEnable() const {
493    return false;
494}
495
496bool SkDisplayable::isDrawable() const {
497    return false;
498}
499
500void SkDisplayable::onEndElement(SkAnimateMaker& ) {}
501
502const SkMemberInfo* SkDisplayable::preferredChild(SkDisplayTypes type) {
503    return NULL;
504}
505
506bool SkDisplayable::resolveIDs(SkAnimateMaker& maker, SkDisplayable* original, SkApply* apply) {
507    return false;
508}
509
510//SkDisplayable* SkDisplayable::resolveTarget(SkAnimateMaker& ) {
511//  return this;
512//}
513
514void SkDisplayable::setChildHasID() {
515}
516
517bool SkDisplayable::setParent(SkDisplayable* ) {
518    return false;
519}
520
521bool SkDisplayable::setProperty(int index, SkScriptValue& ) {
522    //SkASSERT(0);
523    return false;
524}
525
526void 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
554void SkDisplayable::validate() {
555}
556#endif
557
558
559