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 "SkDisplayAdd.h"
11#include "SkAnimateMaker.h"
12#include "SkDisplayApply.h"
13#include "SkDisplayList.h"
14#include "SkDrawable.h"
15#include "SkDrawGroup.h"
16
17#if SK_USE_CONDENSED_INFO == 0
18
19const SkMemberInfo SkAdd::fInfo[] = {
20    SK_MEMBER(mode, AddMode),
21    SK_MEMBER(offset, Int),
22    SK_MEMBER(use, Drawable),
23    SK_MEMBER(where, Drawable)
24};
25
26#endif
27
28// start here;
29// add onEndElement to turn where string into f_Where
30// probably need new SkAnimateMaker::resolve flavor that takes
31// where="id", where="event-target" or not-specified
32// offset="#" (implements before, after, and index if no 'where')
33
34DEFINE_GET_MEMBER(SkAdd);
35
36SkAdd::SkAdd() : mode(kMode_indirect),
37    offset(SK_MaxS32), use(NULL), where(NULL) {
38}
39
40SkDisplayable* SkAdd::deepCopy(SkAnimateMaker* maker) {
41    SkDrawable* saveUse = use;
42    SkDrawable* saveWhere = where;
43    use = NULL;
44    where = NULL;
45    SkAdd* copy = (SkAdd*) INHERITED::deepCopy(maker);
46    copy->use = use = saveUse;
47    copy->where = where = saveWhere;
48    return copy;
49}
50
51bool SkAdd::draw(SkAnimateMaker& maker) {
52    SkASSERT(use);
53    SkASSERT(use->isDrawable());
54    if (mode == kMode_indirect)
55        use->draw(maker);
56    return false;
57}
58
59#ifdef SK_DUMP_ENABLED
60void SkAdd::dump(SkAnimateMaker* maker) {
61    dumpBase(maker);
62    dumpAttrs(maker);
63    if (where)
64        SkDebugf("where=\"%s\" ", where->id);
65    if (mode == kMode_immediate)
66        SkDebugf("mode=\"immediate\" ");
67    SkDebugf(">\n");
68    SkDisplayList::fIndent += 4;
69    int save = SkDisplayList::fDumpIndex;
70    if (use)    //just in case
71        use->dump(maker);
72    SkDisplayList::fIndent -= 4;
73    SkDisplayList::fDumpIndex = save;
74    dumpEnd(maker);
75}
76#endif
77
78bool SkAdd::enable(SkAnimateMaker& maker ) {
79    SkDisplayTypes type = getType();
80    SkDisplayList& displayList = maker.fDisplayList;
81    SkTDDrawableArray* parentList = displayList.getDrawList();
82    if (type == SkType_Add) {
83        if (use == NULL) // not set in apply yet
84            return true;
85    }
86    bool skipAddToParent = true;
87    SkASSERT(type != SkType_Replace || where);
88    SkTDDrawableArray* grandList SK_INIT_TO_AVOID_WARNING;
89    SkGroup* parentGroup = NULL;
90    SkGroup* thisGroup = NULL;
91    int index = where ? displayList.findGroup(where, &parentList, &parentGroup,
92        &thisGroup, &grandList) : 0;
93    if (index < 0)
94        return true;
95    int max = parentList->count();
96    if (where == NULL && type == SkType_Move)
97        index = max;
98    if (offset != SK_MaxS32) {
99        index += offset;
100        if (index > max) {
101            maker.setErrorCode(SkDisplayXMLParserError::kIndexOutOfRange);
102            return true;    // caller should not add
103        }
104    }
105    if (offset < 0 && where == NULL)
106        index += max + 1;
107    switch (type) {
108        case SkType_Add:
109            if (offset == SK_MaxS32 && where == NULL) {
110                if (use->isDrawable()) {
111                    skipAddToParent = mode == kMode_immediate;
112                    if (skipAddToParent) {
113                        if (where == NULL) {
114                            SkTDDrawableArray* useParentList;
115                            index = displayList.findGroup(this, &useParentList, &parentGroup,
116                                &thisGroup, &grandList);
117                            if (index >= 0) {
118                                parentGroup->markCopySize(index);
119                                parentGroup->markCopySet(index);
120                                useParentList->begin()[index] = use;
121                                break;
122                            }
123                        }
124                        *parentList->append() = use;
125                    }
126                }
127                break;
128            } else {
129                if (thisGroup)
130                    thisGroup->markCopySize(index);
131                *parentList->insert(index) = use;
132                if (thisGroup)
133                    thisGroup->markCopySet(index);
134                if (use->isApply())
135                    ((SkApply*) use)->setEmbedded();
136            }
137            break;
138        case SkType_Move: {
139            int priorLocation = parentList->find(use);
140            if (priorLocation < 0)
141                break;
142            *parentList->insert(index) = use;
143            if (index < priorLocation)
144                priorLocation++;
145            parentList->remove(priorLocation);
146            } break;
147        case SkType_Remove: {
148            SkDisplayable* old = (*parentList)[index];
149            if (((SkRemove*)(this))->fDelete) {
150                delete old;
151                goto noHelperNeeded;
152            }
153            for (int inner = 0; inner < maker.fChildren.count(); inner++) {
154                SkDisplayable* child = maker.fChildren[inner];
155                if (child == old || child->contains(old))
156                    goto noHelperNeeded;
157            }
158            if (maker.fHelpers.find(old) < 0)
159                maker.helperAdd(old);
160noHelperNeeded:
161            parentList->remove(index);
162            } break;
163        case SkType_Replace:
164            if (thisGroup) {
165                thisGroup->markCopySize(index);
166                if (thisGroup->markedForDelete(index)) {
167                    SkDisplayable* old = (*parentList)[index];
168                    if (maker.fHelpers.find(old) < 0)
169                        maker.helperAdd(old);
170                }
171            }
172            (*parentList)[index] = use;
173            if (thisGroup)
174                thisGroup->markCopySet(index);
175            break;
176        default:
177            SkASSERT(0);
178    }
179    if (type == SkType_Remove)
180        return true;
181    if (use->hasEnable())
182        use->enable(maker);
183    return skipAddToParent; // append if indirect: *parentList->append() = this;
184}
185
186bool SkAdd::hasEnable() const {
187    return true;
188}
189
190void SkAdd::initialize() {
191    if (use)
192        use->initialize();
193}
194
195bool SkAdd::isDrawable() const {
196    return getType() == SkType_Add && mode == kMode_indirect && offset == SK_MaxS32 &&
197        where == NULL && use != NULL && use->isDrawable();
198}
199
200//SkDisplayable* SkAdd::resolveTarget(SkAnimateMaker& maker) {
201//  return use;
202//}
203
204
205bool SkClear::enable(SkAnimateMaker& maker ) {
206    SkDisplayList& displayList = maker.fDisplayList;
207    displayList.clear();
208    return true;
209}
210
211
212#if SK_USE_CONDENSED_INFO == 0
213
214const SkMemberInfo SkMove::fInfo[] = {
215    SK_MEMBER_INHERITED
216};
217
218#endif
219
220DEFINE_GET_MEMBER(SkMove);
221
222#if SK_USE_CONDENSED_INFO == 0
223
224const SkMemberInfo SkRemove::fInfo[] = {
225    SK_MEMBER_ALIAS(delete, fDelete, Boolean),  // !!! experimental
226    SK_MEMBER(offset, Int),
227    SK_MEMBER(where, Drawable)
228};
229
230#endif
231
232DEFINE_GET_MEMBER(SkRemove);
233
234SkRemove::SkRemove() : fDelete(false) {
235}
236
237#if SK_USE_CONDENSED_INFO == 0
238
239const SkMemberInfo SkReplace::fInfo[] = {
240    SK_MEMBER_INHERITED
241};
242
243#endif
244
245DEFINE_GET_MEMBER(SkReplace);
246