1 /* libs/graphics/animator/SkDisplayAdd.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 "SkDisplayAdd.h" 19 #include "SkAnimateMaker.h" 20 #include "SkDisplayApply.h" 21 #include "SkDisplayList.h" 22 #include "SkDrawable.h" 23 #include "SkDrawGroup.h" 24 25 #if SK_USE_CONDENSED_INFO == 0 26 27 const SkMemberInfo SkAdd::fInfo[] = { 28 SK_MEMBER(mode, AddMode), 29 SK_MEMBER(offset, Int), 30 SK_MEMBER(use, Drawable), 31 SK_MEMBER(where, Drawable) 32 }; 33 34 #endif 35 36 // start here; 37 // add onEndElement to turn where string into f_Where 38 // probably need new SkAnimateMaker::resolve flavor that takes 39 // where="id", where="event-target" or not-specified 40 // offset="#" (implements before, after, and index if no 'where') 41 42 DEFINE_GET_MEMBER(SkAdd); 43 44 SkAdd::SkAdd() : mode(kMode_indirect), 45 offset(SK_MaxS32), use(NULL), where(NULL) { 46 } 47 48 SkDisplayable* SkAdd::deepCopy(SkAnimateMaker* maker) { 49 SkDrawable* saveUse = use; 50 SkDrawable* saveWhere = where; 51 use = NULL; 52 where = NULL; 53 SkAdd* copy = (SkAdd*) INHERITED::deepCopy(maker); 54 copy->use = use = saveUse; 55 copy->where = where = saveWhere; 56 return copy; 57 } 58 59 bool SkAdd::draw(SkAnimateMaker& maker) { 60 SkASSERT(use); 61 SkASSERT(use->isDrawable()); 62 if (mode == kMode_indirect) 63 use->draw(maker); 64 return false; 65 } 66 67 #ifdef SK_DUMP_ENABLED 68 void SkAdd::dump(SkAnimateMaker* maker) { 69 dumpBase(maker); 70 dumpAttrs(maker); 71 if (where) 72 SkDebugf("where=\"%s\" ", where->id); 73 if (mode == kMode_immediate) 74 SkDebugf("mode=\"immediate\" "); 75 SkDebugf(">\n"); 76 SkDisplayList::fIndent += 4; 77 int save = SkDisplayList::fDumpIndex; 78 if (use) //just in case 79 use->dump(maker); 80 SkDisplayList::fIndent -= 4; 81 SkDisplayList::fDumpIndex = save; 82 dumpEnd(maker); 83 } 84 #endif 85 86 bool SkAdd::enable(SkAnimateMaker& maker ) { 87 SkDisplayTypes type = getType(); 88 SkDisplayList& displayList = maker.fDisplayList; 89 SkTDDrawableArray* parentList = displayList.getDrawList(); 90 if (type == SkType_Add) { 91 if (use == NULL) // not set in apply yet 92 return true; 93 } 94 bool skipAddToParent = true; 95 SkASSERT(type != SkType_Replace || where); 96 SkTDDrawableArray* grandList SK_INIT_TO_AVOID_WARNING; 97 SkGroup* parentGroup = NULL; 98 SkGroup* thisGroup = NULL; 99 int index = where ? displayList.findGroup(where, &parentList, &parentGroup, 100 &thisGroup, &grandList) : 0; 101 if (index < 0) 102 return true; 103 int max = parentList->count(); 104 if (where == NULL && type == SkType_Move) 105 index = max; 106 if (offset != SK_MaxS32) { 107 index += offset; 108 if (index > max) { 109 maker.setErrorCode(SkDisplayXMLParserError::kIndexOutOfRange); 110 return true; // caller should not add 111 } 112 } 113 if (offset < 0 && where == NULL) 114 index += max + 1; 115 switch (type) { 116 case SkType_Add: 117 if (offset == SK_MaxS32 && where == NULL) { 118 if (use->isDrawable()) { 119 skipAddToParent = mode == kMode_immediate; 120 if (skipAddToParent) { 121 if (where == NULL) { 122 SkTDDrawableArray* useParentList; 123 index = displayList.findGroup(this, &useParentList, &parentGroup, 124 &thisGroup, &grandList); 125 if (index >= 0) { 126 parentGroup->markCopySize(index); 127 parentGroup->markCopySet(index); 128 useParentList->begin()[index] = use; 129 break; 130 } 131 } 132 *parentList->append() = use; 133 } 134 } 135 break; 136 } else { 137 if (thisGroup) 138 thisGroup->markCopySize(index); 139 *parentList->insert(index) = use; 140 if (thisGroup) 141 thisGroup->markCopySet(index); 142 if (use->isApply()) 143 ((SkApply*) use)->setEmbedded(); 144 } 145 break; 146 case SkType_Move: { 147 int priorLocation = parentList->find(use); 148 if (priorLocation < 0) 149 break; 150 *parentList->insert(index) = use; 151 if (index < priorLocation) 152 priorLocation++; 153 parentList->remove(priorLocation); 154 } break; 155 case SkType_Remove: { 156 SkDisplayable* old = (*parentList)[index]; 157 if (((SkRemove*)(this))->fDelete) { 158 delete old; 159 goto noHelperNeeded; 160 } 161 for (int inner = 0; inner < maker.fChildren.count(); inner++) { 162 SkDisplayable* child = maker.fChildren[inner]; 163 if (child == old || child->contains(old)) 164 goto noHelperNeeded; 165 } 166 if (maker.fHelpers.find(old) < 0) 167 maker.helperAdd(old); 168 noHelperNeeded: 169 parentList->remove(index); 170 } break; 171 case SkType_Replace: 172 if (thisGroup) { 173 thisGroup->markCopySize(index); 174 if (thisGroup->markedForDelete(index)) { 175 SkDisplayable* old = (*parentList)[index]; 176 if (maker.fHelpers.find(old) < 0) 177 maker.helperAdd(old); 178 } 179 } 180 (*parentList)[index] = use; 181 if (thisGroup) 182 thisGroup->markCopySet(index); 183 break; 184 default: 185 SkASSERT(0); 186 } 187 if (type == SkType_Remove) 188 return true; 189 if (use->hasEnable()) 190 use->enable(maker); 191 return skipAddToParent; // append if indirect: *parentList->append() = this; 192 } 193 194 bool SkAdd::hasEnable() const { 195 return true; 196 } 197 198 void SkAdd::initialize() { 199 if (use) 200 use->initialize(); 201 } 202 203 bool SkAdd::isDrawable() const { 204 return getType() == SkType_Add && mode == kMode_indirect && offset == SK_MaxS32 && 205 where == NULL && use != NULL && use->isDrawable(); 206 } 207 208 //SkDisplayable* SkAdd::resolveTarget(SkAnimateMaker& maker) { 209 // return use; 210 //} 211 212 213 bool SkClear::enable(SkAnimateMaker& maker ) { 214 SkDisplayList& displayList = maker.fDisplayList; 215 displayList.clear(); 216 return true; 217 } 218 219 220 #if SK_USE_CONDENSED_INFO == 0 221 222 const SkMemberInfo SkMove::fInfo[] = { 223 SK_MEMBER_INHERITED 224 }; 225 226 #endif 227 228 DEFINE_GET_MEMBER(SkMove); 229 230 #if SK_USE_CONDENSED_INFO == 0 231 232 const SkMemberInfo SkRemove::fInfo[] = { 233 SK_MEMBER_ALIAS(delete, fDelete, Boolean), // !!! experimental 234 SK_MEMBER(offset, Int), 235 SK_MEMBER(where, Drawable) 236 }; 237 238 #endif 239 240 DEFINE_GET_MEMBER(SkRemove); 241 242 SkRemove::SkRemove() : fDelete(false) { 243 } 244 245 #if SK_USE_CONDENSED_INFO == 0 246 247 const SkMemberInfo SkReplace::fInfo[] = { 248 SK_MEMBER_INHERITED 249 }; 250 251 #endif 252 253 DEFINE_GET_MEMBER(SkReplace); 254 255