blob: b1b7f0a429411676ae1bc5aac91845c6ff7aaac5 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
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
reed@android.com8a1c16f2008-12-17 15:59:43 +00009
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;
reed986ca612014-11-26 08:50:45 -080039 for (SkADrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000040 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
tfarina@chromium.org1d3c4112012-12-03 14:38:08 +000052bool SkGroup::addChild(SkAnimateMaker& , SkDisplayable* child) {
rmistry@google.comd6176b02012-08-23 18:14:13 +000053 SkASSERT(child);
reed@android.com8a1c16f2008-12-17 15:59:43 +000054// SkASSERT(child->isDrawable());
reed986ca612014-11-26 08:50:45 -080055 *fChildren.append() = (SkADrawable*) child;
reed@android.com8a1c16f2008-12-17 15:59:43 +000056 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) {
reed986ca612014-11-26 08:50:45 -080065 for (SkADrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
66 SkADrawable* drawable = *ptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +000067 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);
reed986ca612014-11-26 08:50:45 -080086 for (SkADrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000087 SkDisplayable* displayable = (SkDisplayable*)*ptr;
88 SkDisplayable* deeperCopy = displayable->deepCopy(maker);
tfarina@chromium.org1d3c4112012-12-03 14:38:08 +000089 ((SkGroup*)copy)->addChild(*maker, deeperCopy);
reed@android.com8a1c16f2008-12-17 15:59:43 +000090 }
91 return copy;
92}
93
94bool SkGroup::doEvent(SkDisplayEvent::Kind kind, SkEventState* state) {
95 bool handled = false;
reed986ca612014-11-26 08:50:45 -080096 for (SkADrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
97 SkADrawable* drawable = *ptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +000098 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;
reed986ca612014-11-26 08:50:45 -0800108 for (SkADrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
109 SkADrawable* drawable = *ptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000110 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;
reed986ca612014-11-26 08:50:45 -0800139 for (SkADrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000140 if (closedYet == false) {
141 closedYet = true;
142 SkDebugf(">\n");
143 }
reed986ca612014-11-26 08:50:45 -0800144 SkADrawable* drawable = *ptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000145 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() {
reed986ca612014-11-26 08:50:45 -0800157 for (SkADrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
158 SkADrawable* drawable = *ptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000159 drawable->dumpEvents();
160 }
161}
162#endif
163
164bool SkGroup::enable(SkAnimateMaker& maker ) {
165 reset();
reed986ca612014-11-26 08:50:45 -0800166 for (SkADrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
167 SkADrawable* drawable = *ptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000168 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
reed986ca612014-11-26 08:50:45 -0800175int SkGroup::findGroup(SkADrawable* match, SkTDDrawableArray** list,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000176 SkGroup** parent, SkGroup** found, SkTDDrawableArray** grandList) {
177 *list = &fChildren;
reed986ca612014-11-26 08:50:45 -0800178 for (SkADrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
179 SkADrawable* drawable = *ptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000180 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
reed986ca612014-11-26 08:50:45 -0800199bool SkGroup::ifCondition(SkAnimateMaker& maker, SkADrawable*,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000200 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() {
reed986ca612014-11-26 08:50:45 -0800220 for (SkADrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
221 SkADrawable* drawable = *ptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000222 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;
reed986ca612014-11-26 08:50:45 -0800256 for (SkADrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000257 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;
reed986ca612014-11-26 08:50:45 -0800271 SkADrawable** originalPtr = originalChildren.begin();
272 SkADrawable** ptr = fChildren.begin();
273 SkADrawable** end = fChildren.end();
274 SkADrawable** origChild = ((SkGroup*) orig)->fChildren.begin();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000275 while (ptr < end) {
reed986ca612014-11-26 08:50:45 -0800276 SkADrawable* drawable = *ptr++;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000277 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) {
reed986ca612014-11-26 08:50:45 -0800285 for (SkADrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
286 SkADrawable* drawable = *ptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000287 if (drawable->isDrawable() == false)
288 continue;
289 drawable->setSteps(steps);
290 }
291}
292
293#ifdef SK_DEBUG
294void SkGroup::validate() {
reed986ca612014-11-26 08:50:45 -0800295 for (SkADrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
296 SkADrawable* drawable = *ptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000297 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}