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 "SkDrawGroup.h"
11 #include "SkAnimateMaker.h"
12 #include "SkAnimatorScript.h"
13 #include "SkCanvas.h"
14 #include "SkDisplayApply.h"
15 #include "SkPaint.h"
16 #ifdef SK_DEBUG
17 #include "SkDisplayList.h"
18 #endif
19 
20 #if SK_USE_CONDENSED_INFO == 0
21 
22 const SkMemberInfo SkGroup::fInfo[] = {
23     SK_MEMBER(condition, String),
24     SK_MEMBER(enableCondition, String)
25 };
26 
27 #endif
28 
29 DEFINE_GET_MEMBER(SkGroup);
30 
SkGroup()31 SkGroup::SkGroup() : fParentList(nullptr), fOriginal(nullptr) {
32 }
33 
~SkGroup()34 SkGroup::~SkGroup() {
35     if (fOriginal)  // has been copied
36         return;
37     int index = 0;
38     int max = fCopies.count() << 5;
39     for (SkADrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
40         if (index >= max || markedForDelete(index))
41             delete *ptr;
42 //      else {
43 //          SkApply* apply = (SkApply*) *ptr;
44 //          SkASSERT(apply->isApply());
45 //          SkASSERT(apply->getScope());
46 //          delete apply->getScope();
47 //      }
48         index++;
49     }
50 }
51 
addChild(SkAnimateMaker &,SkDisplayable * child)52 bool SkGroup::addChild(SkAnimateMaker& , SkDisplayable* child) {
53     SkASSERT(child);
54 //  SkASSERT(child->isDrawable());
55     *fChildren.append() = (SkADrawable*) child;
56     if (child->isGroup()) {
57         SkGroup* groupie = (SkGroup*) child;
58         SkASSERT(groupie->fParentList == nullptr);
59         groupie->fParentList = &fChildren;
60     }
61     return true;
62 }
63 
contains(SkDisplayable * match)64 bool SkGroup::contains(SkDisplayable* match) {
65     for (SkADrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
66         SkADrawable* drawable = *ptr;
67         if (drawable == match || drawable->contains(match))
68             return true;
69     }
70     return false;
71 }
72 
copy()73 SkGroup* SkGroup::copy() {
74     SkGroup* result = new SkGroup();
75     result->fOriginal = this;
76     result->fChildren = fChildren;
77     return result;
78 }
79 
copySet(int index)80 SkBool SkGroup::copySet(int index) {
81     return (fCopies[index >> 5] & 1 << (index & 0x1f)) != 0;
82 }
83 
deepCopy(SkAnimateMaker * maker)84 SkDisplayable* SkGroup::deepCopy(SkAnimateMaker* maker) {
85     SkDisplayable* copy = INHERITED::deepCopy(maker);
86     for (SkADrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
87         SkDisplayable* displayable = (SkDisplayable*)*ptr;
88         SkDisplayable* deeperCopy = displayable->deepCopy(maker);
89         ((SkGroup*)copy)->addChild(*maker, deeperCopy);
90     }
91     return copy;
92 }
93 
doEvent(SkDisplayEvent::Kind kind,SkEventState * state)94 bool SkGroup::doEvent(SkDisplayEvent::Kind kind, SkEventState* state) {
95     bool handled = false;
96     for (SkADrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
97         SkADrawable* drawable = *ptr;
98         if (drawable->isDrawable() == false)
99             continue;
100         handled |= drawable->doEvent(kind, state);
101     }
102     return handled;
103 }
104 
draw(SkAnimateMaker & maker)105 bool SkGroup::draw(SkAnimateMaker& maker) {
106     bool conditionTrue = ifCondition(maker, this, condition);
107     bool result = false;
108     for (SkADrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
109         SkADrawable* drawable = *ptr;
110         if (drawable->isDrawable() == false)
111             continue;
112         if (conditionTrue == false) {
113             if (drawable->isApply())
114                 ((SkApply*) drawable)->disable();
115             continue;
116         }
117         maker.validate();
118         result |= drawable->draw(maker);
119         maker.validate();
120     }
121     return result;
122 }
123 
124 #ifdef SK_DUMP_ENABLED
dump(SkAnimateMaker * maker)125 void SkGroup::dump(SkAnimateMaker* maker) {
126     dumpBase(maker);
127     if (condition.size() > 0)
128         SkDebugf("condition=\"%s\" ", condition.c_str());
129     if (enableCondition.size() > 0)
130         SkDebugf("enableCondition=\"%s\" ", enableCondition.c_str());
131     dumpDrawables(maker);
132 }
133 
dumpDrawables(SkAnimateMaker * maker)134 void SkGroup::dumpDrawables(SkAnimateMaker* maker) {
135     SkDisplayList::fIndent += 4;
136     int save = SkDisplayList::fDumpIndex;
137     SkDisplayList::fDumpIndex = 0;
138     bool closedYet = false;
139     for (SkADrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
140         if (closedYet == false) {
141             closedYet = true;
142             SkDebugf(">\n");
143         }
144         SkADrawable* drawable = *ptr;
145         drawable->dump(maker);
146         SkDisplayList::fDumpIndex++;
147     }
148     SkDisplayList::fIndent -= 4;
149     SkDisplayList::fDumpIndex = save;
150     if (closedYet) //we had children, now it's time to close the group
151         dumpEnd(maker);
152     else    //no children
153         SkDebugf("/>\n");
154 }
155 
dumpEvents()156 void SkGroup::dumpEvents() {
157     for (SkADrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
158         SkADrawable* drawable = *ptr;
159         drawable->dumpEvents();
160     }
161 }
162 #endif
163 
enable(SkAnimateMaker & maker)164 bool SkGroup::enable(SkAnimateMaker& maker ) {
165     reset();
166     for (SkADrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
167         SkADrawable* drawable = *ptr;
168         if (ifCondition(maker, drawable, enableCondition) == false)
169             continue;
170         drawable->enable(maker);
171     }
172     return true;    // skip add; already added so that scope is findable by children
173 }
174 
findGroup(SkADrawable * match,SkTDDrawableArray ** list,SkGroup ** parent,SkGroup ** found,SkTDDrawableArray ** grandList)175 int SkGroup::findGroup(SkADrawable* match,  SkTDDrawableArray** list,
176                  SkGroup** parent, SkGroup** found, SkTDDrawableArray** grandList) {
177     *list = &fChildren;
178     for (SkADrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
179         SkADrawable* drawable = *ptr;
180         if (drawable->isGroup()) {
181             SkGroup* childGroup = (SkGroup*) drawable;
182             if (childGroup->fOriginal == match)
183                 goto foundMatch;
184         }
185         if (drawable == match) {
186 foundMatch:
187             *parent = this;
188             return (int) (ptr - fChildren.begin());
189         }
190     }
191     *grandList = &fChildren;
192     return SkDisplayList::SearchForMatch(match, list, parent, found, grandList);
193 }
194 
hasEnable() const195 bool SkGroup::hasEnable() const {
196     return true;
197 }
198 
ifCondition(SkAnimateMaker & maker,SkADrawable *,SkString & conditionString)199 bool SkGroup::ifCondition(SkAnimateMaker& maker, SkADrawable*,
200         SkString& conditionString) {
201     if (conditionString.size() == 0)
202         return true;
203     int32_t result;
204     bool success = SkAnimatorScript::EvaluateInt(maker, this, conditionString.c_str(), &result);
205 #ifdef SK_DUMP_ENABLED
206     if (maker.fDumpGConditions) {
207         SkDebugf("group: ");
208         dumpBase(&maker);
209         SkDebugf("condition=%s ", conditionString.c_str());
210         if (success == false)
211             SkDebugf("(script failed)\n");
212         else
213             SkDebugf("success=%s\n", result != 0 ? "true" : "false");
214     }
215 #endif
216     return success && result != 0;
217 }
218 
initialize()219 void SkGroup::initialize() {
220     for (SkADrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
221         SkADrawable* drawable = *ptr;
222         if (drawable->isDrawable() == false)
223             continue;
224         drawable->initialize();
225     }
226 }
227 
markCopyClear(int index)228 void SkGroup::markCopyClear(int index) {
229     if (index < 0)
230         index = fChildren.count();
231     fCopies[index >> 5] &= ~(1 << (index & 0x1f));
232 }
233 
markCopySet(int index)234 void SkGroup::markCopySet(int index) {
235     if (index < 0)
236         index = fChildren.count();
237     fCopies[index >> 5] |= 1 << (index & 0x1f);
238 }
239 
markCopySize(int index)240 void SkGroup::markCopySize(int index) {
241     if (index < 0)
242         index = fChildren.count() + 1;
243     int oldLongs = fCopies.count();
244     int newLongs = (index >> 5) + 1;
245     if (oldLongs < newLongs) {
246         fCopies.setCount(newLongs);
247         memset(&fCopies[oldLongs], 0, (newLongs - oldLongs) << 2);
248     }
249 }
250 
reset()251 void SkGroup::reset() {
252     if (fOriginal)  // has been copied
253         return;
254     int index = 0;
255     int max = fCopies.count() << 5;
256     for (SkADrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
257         if (index >= max || copySet(index) == false)
258             continue;
259         SkApply* apply = (SkApply*) *ptr;
260         SkASSERT(apply->isApply());
261         SkASSERT(apply->getScope());
262         *ptr = apply->getScope();
263         markCopyClear(index);
264         index++;
265     }
266 }
267 
resolveIDs(SkAnimateMaker & maker,SkDisplayable * orig,SkApply * apply)268 bool SkGroup::resolveIDs(SkAnimateMaker& maker, SkDisplayable* orig, SkApply* apply) {
269     SkGroup* original = (SkGroup*) orig;
270     SkTDDrawableArray& originalChildren = original->fChildren;
271     SkADrawable** originalPtr = originalChildren.begin();
272     SkADrawable** ptr = fChildren.begin();
273     SkADrawable** end = fChildren.end();
274     SkADrawable** origChild = ((SkGroup*) orig)->fChildren.begin();
275     while (ptr < end) {
276         SkADrawable* drawable = *ptr++;
277         maker.resolveID(drawable, *origChild++);
278         if (drawable->resolveIDs(maker, *originalPtr++, apply) == true)
279             return true; // failed
280     }
281     return false;
282 }
283 
setSteps(int steps)284 void SkGroup::setSteps(int steps) {
285     for (SkADrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
286         SkADrawable* drawable = *ptr;
287         if (drawable->isDrawable() == false)
288             continue;
289         drawable->setSteps(steps);
290     }
291 }
292 
293 #ifdef SK_DEBUG
validate()294 void SkGroup::validate() {
295     for (SkADrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
296         SkADrawable* drawable = *ptr;
297         drawable->validate();
298     }
299 }
300 #endif
301 
302 #if SK_USE_CONDENSED_INFO == 0
303 
304 const SkMemberInfo SkSave::fInfo[] = {
305     SK_MEMBER_INHERITED
306 };
307 
308 #endif
309 
310 DEFINE_GET_MEMBER(SkSave);
311 
draw(SkAnimateMaker & maker)312 bool SkSave::draw(SkAnimateMaker& maker) {
313     maker.fCanvas->save();
314     SkPaint* save = maker.fPaint;
315     SkPaint local = SkPaint(*maker.fPaint);
316     maker.fPaint = &local;
317     bool result = INHERITED::draw(maker);
318     maker.fPaint = save;
319     maker.fCanvas->restore();
320     return result;
321 }
322