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