michael@0: michael@0: /* michael@0: * Copyright 2006 The Android Open Source Project michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: michael@0: #include "SkDisplayAdd.h" michael@0: #include "SkAnimateMaker.h" michael@0: #include "SkDisplayApply.h" michael@0: #include "SkDisplayList.h" michael@0: #include "SkDrawable.h" michael@0: #include "SkDrawGroup.h" michael@0: michael@0: #if SK_USE_CONDENSED_INFO == 0 michael@0: michael@0: const SkMemberInfo SkAdd::fInfo[] = { michael@0: SK_MEMBER(mode, AddMode), michael@0: SK_MEMBER(offset, Int), michael@0: SK_MEMBER(use, Drawable), michael@0: SK_MEMBER(where, Drawable) michael@0: }; michael@0: michael@0: #endif michael@0: michael@0: // start here; michael@0: // add onEndElement to turn where string into f_Where michael@0: // probably need new SkAnimateMaker::resolve flavor that takes michael@0: // where="id", where="event-target" or not-specified michael@0: // offset="#" (implements before, after, and index if no 'where') michael@0: michael@0: DEFINE_GET_MEMBER(SkAdd); michael@0: michael@0: SkAdd::SkAdd() : mode(kMode_indirect), michael@0: offset(SK_MaxS32), use(NULL), where(NULL) { michael@0: } michael@0: michael@0: SkDisplayable* SkAdd::deepCopy(SkAnimateMaker* maker) { michael@0: SkDrawable* saveUse = use; michael@0: SkDrawable* saveWhere = where; michael@0: use = NULL; michael@0: where = NULL; michael@0: SkAdd* copy = (SkAdd*) INHERITED::deepCopy(maker); michael@0: copy->use = use = saveUse; michael@0: copy->where = where = saveWhere; michael@0: return copy; michael@0: } michael@0: michael@0: bool SkAdd::draw(SkAnimateMaker& maker) { michael@0: SkASSERT(use); michael@0: SkASSERT(use->isDrawable()); michael@0: if (mode == kMode_indirect) michael@0: use->draw(maker); michael@0: return false; michael@0: } michael@0: michael@0: #ifdef SK_DUMP_ENABLED michael@0: void SkAdd::dump(SkAnimateMaker* maker) { michael@0: dumpBase(maker); michael@0: dumpAttrs(maker); michael@0: if (where) michael@0: SkDebugf("where=\"%s\" ", where->id); michael@0: if (mode == kMode_immediate) michael@0: SkDebugf("mode=\"immediate\" "); michael@0: SkDebugf(">\n"); michael@0: SkDisplayList::fIndent += 4; michael@0: int save = SkDisplayList::fDumpIndex; michael@0: if (use) //just in case michael@0: use->dump(maker); michael@0: SkDisplayList::fIndent -= 4; michael@0: SkDisplayList::fDumpIndex = save; michael@0: dumpEnd(maker); michael@0: } michael@0: #endif michael@0: michael@0: bool SkAdd::enable(SkAnimateMaker& maker ) { michael@0: SkDisplayTypes type = getType(); michael@0: SkDisplayList& displayList = maker.fDisplayList; michael@0: SkTDDrawableArray* parentList = displayList.getDrawList(); michael@0: if (type == SkType_Add) { michael@0: if (use == NULL) // not set in apply yet michael@0: return true; michael@0: } michael@0: bool skipAddToParent = true; michael@0: SkASSERT(type != SkType_Replace || where); michael@0: SkTDDrawableArray* grandList SK_INIT_TO_AVOID_WARNING; michael@0: SkGroup* parentGroup = NULL; michael@0: SkGroup* thisGroup = NULL; michael@0: int index = where ? displayList.findGroup(where, &parentList, &parentGroup, michael@0: &thisGroup, &grandList) : 0; michael@0: if (index < 0) michael@0: return true; michael@0: int max = parentList->count(); michael@0: if (where == NULL && type == SkType_Move) michael@0: index = max; michael@0: if (offset != SK_MaxS32) { michael@0: index += offset; michael@0: if (index > max) { michael@0: maker.setErrorCode(SkDisplayXMLParserError::kIndexOutOfRange); michael@0: return true; // caller should not add michael@0: } michael@0: } michael@0: if (offset < 0 && where == NULL) michael@0: index += max + 1; michael@0: switch (type) { michael@0: case SkType_Add: michael@0: if (offset == SK_MaxS32 && where == NULL) { michael@0: if (use->isDrawable()) { michael@0: skipAddToParent = mode == kMode_immediate; michael@0: if (skipAddToParent) { michael@0: if (where == NULL) { michael@0: SkTDDrawableArray* useParentList; michael@0: index = displayList.findGroup(this, &useParentList, &parentGroup, michael@0: &thisGroup, &grandList); michael@0: if (index >= 0) { michael@0: parentGroup->markCopySize(index); michael@0: parentGroup->markCopySet(index); michael@0: useParentList->begin()[index] = use; michael@0: break; michael@0: } michael@0: } michael@0: *parentList->append() = use; michael@0: } michael@0: } michael@0: break; michael@0: } else { michael@0: if (thisGroup) michael@0: thisGroup->markCopySize(index); michael@0: *parentList->insert(index) = use; michael@0: if (thisGroup) michael@0: thisGroup->markCopySet(index); michael@0: if (use->isApply()) michael@0: ((SkApply*) use)->setEmbedded(); michael@0: } michael@0: break; michael@0: case SkType_Move: { michael@0: int priorLocation = parentList->find(use); michael@0: if (priorLocation < 0) michael@0: break; michael@0: *parentList->insert(index) = use; michael@0: if (index < priorLocation) michael@0: priorLocation++; michael@0: parentList->remove(priorLocation); michael@0: } break; michael@0: case SkType_Remove: { michael@0: SkDisplayable* old = (*parentList)[index]; michael@0: if (((SkRemove*)(this))->fDelete) { michael@0: delete old; michael@0: goto noHelperNeeded; michael@0: } michael@0: for (int inner = 0; inner < maker.fChildren.count(); inner++) { michael@0: SkDisplayable* child = maker.fChildren[inner]; michael@0: if (child == old || child->contains(old)) michael@0: goto noHelperNeeded; michael@0: } michael@0: if (maker.fHelpers.find(old) < 0) michael@0: maker.helperAdd(old); michael@0: noHelperNeeded: michael@0: parentList->remove(index); michael@0: } break; michael@0: case SkType_Replace: michael@0: if (thisGroup) { michael@0: thisGroup->markCopySize(index); michael@0: if (thisGroup->markedForDelete(index)) { michael@0: SkDisplayable* old = (*parentList)[index]; michael@0: if (maker.fHelpers.find(old) < 0) michael@0: maker.helperAdd(old); michael@0: } michael@0: } michael@0: (*parentList)[index] = use; michael@0: if (thisGroup) michael@0: thisGroup->markCopySet(index); michael@0: break; michael@0: default: michael@0: SkASSERT(0); michael@0: } michael@0: if (type == SkType_Remove) michael@0: return true; michael@0: if (use->hasEnable()) michael@0: use->enable(maker); michael@0: return skipAddToParent; // append if indirect: *parentList->append() = this; michael@0: } michael@0: michael@0: bool SkAdd::hasEnable() const { michael@0: return true; michael@0: } michael@0: michael@0: void SkAdd::initialize() { michael@0: if (use) michael@0: use->initialize(); michael@0: } michael@0: michael@0: bool SkAdd::isDrawable() const { michael@0: return getType() == SkType_Add && mode == kMode_indirect && offset == SK_MaxS32 && michael@0: where == NULL && use != NULL && use->isDrawable(); michael@0: } michael@0: michael@0: //SkDisplayable* SkAdd::resolveTarget(SkAnimateMaker& maker) { michael@0: // return use; michael@0: //} michael@0: michael@0: michael@0: bool SkClear::enable(SkAnimateMaker& maker ) { michael@0: SkDisplayList& displayList = maker.fDisplayList; michael@0: displayList.clear(); michael@0: return true; michael@0: } michael@0: michael@0: michael@0: #if SK_USE_CONDENSED_INFO == 0 michael@0: michael@0: const SkMemberInfo SkMove::fInfo[] = { michael@0: SK_MEMBER_INHERITED michael@0: }; michael@0: michael@0: #endif michael@0: michael@0: DEFINE_GET_MEMBER(SkMove); michael@0: michael@0: #if SK_USE_CONDENSED_INFO == 0 michael@0: michael@0: const SkMemberInfo SkRemove::fInfo[] = { michael@0: SK_MEMBER_ALIAS(delete, fDelete, Boolean), // !!! experimental michael@0: SK_MEMBER(offset, Int), michael@0: SK_MEMBER(where, Drawable) michael@0: }; michael@0: michael@0: #endif michael@0: michael@0: DEFINE_GET_MEMBER(SkRemove); michael@0: michael@0: SkRemove::SkRemove() : fDelete(false) { michael@0: } michael@0: michael@0: #if SK_USE_CONDENSED_INFO == 0 michael@0: michael@0: const SkMemberInfo SkReplace::fInfo[] = { michael@0: SK_MEMBER_INHERITED michael@0: }; michael@0: michael@0: #endif michael@0: michael@0: DEFINE_GET_MEMBER(SkReplace);