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
22const SkMemberInfo SkGroup::fInfo[] = {
23    SK_MEMBER(condition, String),
24    SK_MEMBER(enableCondition, String)
25};
26
27#endif
28
29DEFINE_GET_MEMBER(SkGroup);
30
31SkGroup::SkGroup() : fParentList(NULL), fOriginal(NULL) {
32}
33
34SkGroup::~SkGroup() {
35    if (fOriginal)  // has been copied
36        return;
37    int index = 0;
38    int max = fCopies.count() << 5;
39    for (SkDrawable** 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
52bool SkGroup::addChild(SkAnimateMaker& , SkDisplayable* child) {
53    SkASSERT(child);
54//  SkASSERT(child->isDrawable());
55    *fChildren.append() = (SkDrawable*) child;
56    if (child->isGroup()) {
57        SkGroup* groupie = (SkGroup*) child;
58        SkASSERT(groupie->fParentList == NULL);
59        groupie->fParentList = &fChildren;
60    }
61    return true;
62}
63
64bool SkGroup::contains(SkDisplayable* match) {
65    for (SkDrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
66        SkDrawable* drawable = *ptr;
67        if (drawable == match || drawable->contains(match))
68            return true;
69    }
70    return false;
71}
72
73SkGroup* SkGroup::copy() {
74    SkGroup* result = new SkGroup();
75    result->fOriginal = this;
76    result->fChildren = fChildren;
77    return result;
78}
79
80SkBool SkGroup::copySet(int index) {
81    return (fCopies[index >> 5] & 1 << (index & 0x1f)) != 0;
82}
83
84SkDisplayable* SkGroup::deepCopy(SkAnimateMaker* maker) {
85    SkDisplayable* copy = INHERITED::deepCopy(maker);
86    for (SkDrawable** 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
94bool SkGroup::doEvent(SkDisplayEvent::Kind kind, SkEventState* state) {
95    bool handled = false;
96    for (SkDrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
97        SkDrawable* drawable = *ptr;
98        if (drawable->isDrawable() == false)
99            continue;
100        handled |= drawable->doEvent(kind, state);
101    }
102    return handled;
103}
104
105bool SkGroup::draw(SkAnimateMaker& maker) {
106    bool conditionTrue = ifCondition(maker, this, condition);
107    bool result = false;
108    for (SkDrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
109        SkDrawable* 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
125void 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
134void SkGroup::dumpDrawables(SkAnimateMaker* maker) {
135    SkDisplayList::fIndent += 4;
136    int save = SkDisplayList::fDumpIndex;
137    SkDisplayList::fDumpIndex = 0;
138    bool closedYet = false;
139    for (SkDrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
140        if (closedYet == false) {
141            closedYet = true;
142            SkDebugf(">\n");
143        }
144        SkDrawable* 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
156void SkGroup::dumpEvents() {
157    for (SkDrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
158        SkDrawable* drawable = *ptr;
159        drawable->dumpEvents();
160    }
161}
162#endif
163
164bool SkGroup::enable(SkAnimateMaker& maker ) {
165    reset();
166    for (SkDrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
167        SkDrawable* 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
175int SkGroup::findGroup(SkDrawable* match,  SkTDDrawableArray** list,
176                 SkGroup** parent, SkGroup** found, SkTDDrawableArray** grandList) {
177    *list = &fChildren;
178    for (SkDrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
179        SkDrawable* drawable = *ptr;
180        if (drawable->isGroup()) {
181            SkGroup* childGroup = (SkGroup*) drawable;
182            if (childGroup->fOriginal == match)
183                goto foundMatch;
184        }
185        if (drawable == match) {
186foundMatch:
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
195bool SkGroup::hasEnable() const {
196    return true;
197}
198
199bool SkGroup::ifCondition(SkAnimateMaker& maker, SkDrawable*,
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
219void SkGroup::initialize() {
220    for (SkDrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
221        SkDrawable* drawable = *ptr;
222        if (drawable->isDrawable() == false)
223            continue;
224        drawable->initialize();
225    }
226}
227
228void SkGroup::markCopyClear(int index) {
229    if (index < 0)
230        index = fChildren.count();
231    fCopies[index >> 5] &= ~(1 << (index & 0x1f));
232}
233
234void SkGroup::markCopySet(int index) {
235    if (index < 0)
236        index = fChildren.count();
237    fCopies[index >> 5] |= 1 << (index & 0x1f);
238}
239
240void 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
251void SkGroup::reset() {
252    if (fOriginal)  // has been copied
253        return;
254    int index = 0;
255    int max = fCopies.count() << 5;
256    for (SkDrawable** 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
268bool SkGroup::resolveIDs(SkAnimateMaker& maker, SkDisplayable* orig, SkApply* apply) {
269    SkGroup* original = (SkGroup*) orig;
270    SkTDDrawableArray& originalChildren = original->fChildren;
271    SkDrawable** originalPtr = originalChildren.begin();
272    SkDrawable** ptr = fChildren.begin();
273    SkDrawable** end = fChildren.end();
274    SkDrawable** origChild = ((SkGroup*) orig)->fChildren.begin();
275    while (ptr < end) {
276        SkDrawable* 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
284void SkGroup::setSteps(int steps) {
285    for (SkDrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
286        SkDrawable* drawable = *ptr;
287        if (drawable->isDrawable() == false)
288            continue;
289        drawable->setSteps(steps);
290    }
291}
292
293#ifdef SK_DEBUG
294void SkGroup::validate() {
295    for (SkDrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
296        SkDrawable* drawable = *ptr;
297        drawable->validate();
298    }
299}
300#endif
301
302#if SK_USE_CONDENSED_INFO == 0
303
304const SkMemberInfo SkSave::fInfo[] = {
305    SK_MEMBER_INHERITED
306};
307
308#endif
309
310DEFINE_GET_MEMBER(SkSave);
311
312bool 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