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 31 SkGroup::SkGroup() : fParentList(NULL), fOriginal(NULL) { 32 } 33 34 SkGroup::~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 52 bool 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 64 bool 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 73 SkGroup* SkGroup::copy() { 74 SkGroup* result = new SkGroup(); 75 result->fOriginal = this; 76 result->fChildren = fChildren; 77 return result; 78 } 79 80 SkBool SkGroup::copySet(int index) { 81 return (fCopies[index >> 5] & 1 << (index & 0x1f)) != 0; 82 } 83 84 SkDisplayable* 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 94 bool 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 105 bool 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 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 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 (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 156 void SkGroup::dumpEvents() { 157 for (SkDrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) { 158 SkDrawable* drawable = *ptr; 159 drawable->dumpEvents(); 160 } 161 } 162 #endif 163 164 bool 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 175 int 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) { 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 195 bool SkGroup::hasEnable() const { 196 return true; 197 } 198 199 bool 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 219 void 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 228 void SkGroup::markCopyClear(int index) { 229 if (index < 0) 230 index = fChildren.count(); 231 fCopies[index >> 5] &= ~(1 << (index & 0x1f)); 232 } 233 234 void SkGroup::markCopySet(int index) { 235 if (index < 0) 236 index = fChildren.count(); 237 fCopies[index >> 5] |= 1 << (index & 0x1f); 238 } 239 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 251 void 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 268 bool 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 284 void 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 294 void 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 304 const SkMemberInfo SkSave::fInfo[] = { 305 SK_MEMBER_INHERITED 306 }; 307 308 #endif 309 310 DEFINE_GET_MEMBER(SkSave); 311 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