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