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