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 "SkADrawable.h"
15 #include "SkDrawGroup.h"
16 
17 #if SK_USE_CONDENSED_INFO == 0
18 
19 const 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 
34 DEFINE_GET_MEMBER(SkAdd);
35 
SkAdd()36 SkAdd::SkAdd() : mode(kMode_indirect),
37     offset(SK_MaxS32), use(nullptr), where(nullptr) {
38 }
39 
deepCopy(SkAnimateMaker * maker)40 SkDisplayable* SkAdd::deepCopy(SkAnimateMaker* maker) {
41     SkADrawable* saveUse = use;
42     SkADrawable* saveWhere = where;
43     use = nullptr;
44     where = nullptr;
45     SkAdd* copy = (SkAdd*) INHERITED::deepCopy(maker);
46     copy->use = use = saveUse;
47     copy->where = where = saveWhere;
48     return copy;
49 }
50 
draw(SkAnimateMaker & maker)51 bool 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
dump(SkAnimateMaker * maker)60 void 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 
enable(SkAnimateMaker & maker)78 bool 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 == nullptr) // 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 = nullptr;
90     SkGroup* thisGroup = nullptr;
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 == nullptr && 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 == nullptr)
106         index += max + 1;
107     switch (type) {
108         case SkType_Add:
109             if (offset == SK_MaxS32 && where == nullptr) {
110                 if (use->isDrawable()) {
111                     skipAddToParent = mode == kMode_immediate;
112                     if (skipAddToParent) {
113                         if (where == nullptr) {
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);
160 noHelperNeeded:
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 
hasEnable() const186 bool SkAdd::hasEnable() const {
187     return true;
188 }
189 
initialize()190 void SkAdd::initialize() {
191     if (use)
192         use->initialize();
193 }
194 
isDrawable() const195 bool SkAdd::isDrawable() const {
196     return getType() == SkType_Add && mode == kMode_indirect && offset == SK_MaxS32 &&
197         where == nullptr && use != nullptr && use->isDrawable();
198 }
199 
200 //SkDisplayable* SkAdd::resolveTarget(SkAnimateMaker& maker) {
201 //  return use;
202 //}
203 
204 
enable(SkAnimateMaker & maker)205 bool 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 
214 const SkMemberInfo SkMove::fInfo[] = {
215     SK_MEMBER_INHERITED
216 };
217 
218 #endif
219 
220 DEFINE_GET_MEMBER(SkMove);
221 
222 #if SK_USE_CONDENSED_INFO == 0
223 
224 const 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 
232 DEFINE_GET_MEMBER(SkRemove);
233 
SkRemove()234 SkRemove::SkRemove() : fDelete(false) {
235 }
236 
237 #if SK_USE_CONDENSED_INFO == 0
238 
239 const SkMemberInfo SkReplace::fInfo[] = {
240     SK_MEMBER_INHERITED
241 };
242 
243 #endif
244 
245 DEFINE_GET_MEMBER(SkReplace);
246