1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
8ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDrawGroup.h"
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkAnimateMaker.h"
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkAnimatorScript.h"
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkCanvas.h"
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDisplayApply.h"
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPaint.h"
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDisplayList.h"
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if SK_USE_CONDENSED_INFO == 0
218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMemberInfo SkGroup::fInfo[] = {
238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SK_MEMBER(condition, String),
248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SK_MEMBER(enableCondition, String)
258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comDEFINE_GET_MEMBER(SkGroup);
308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
312880df2609eba09b555ca37be04b6ad89290c765Tom HudsonSkGroup::SkGroup() : fParentList(nullptr), fOriginal(nullptr) {
328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkGroup::~SkGroup() {
358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fOriginal)  // has been copied
368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int index = 0;
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int max = fCopies.count() << 5;
39986ca61cf7be3ec590f8820e9b7ba042ac2948fereed    for (SkADrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (index >= max || markedForDelete(index))
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            delete *ptr;
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//      else {
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//          SkApply* apply = (SkApply*) *ptr;
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//          SkASSERT(apply->isApply());
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//          SkASSERT(apply->getScope());
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//          delete apply->getScope();
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//      }
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        index++;
498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
521d3c411f5e4d2ad31bc92b3a85957004329ac00dtfarina@chromium.orgbool SkGroup::addChild(SkAnimateMaker& , SkDisplayable* child) {
53d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com    SkASSERT(child);
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//  SkASSERT(child->isDrawable());
55986ca61cf7be3ec590f8820e9b7ba042ac2948fereed    *fChildren.append() = (SkADrawable*) child;
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (child->isGroup()) {
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkGroup* groupie = (SkGroup*) child;
582880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        SkASSERT(groupie->fParentList == nullptr);
598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        groupie->fParentList = &fChildren;
608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return true;
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkGroup::contains(SkDisplayable* match) {
65986ca61cf7be3ec590f8820e9b7ba042ac2948fereed    for (SkADrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
66986ca61cf7be3ec590f8820e9b7ba042ac2948fereed        SkADrawable* drawable = *ptr;
678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (drawable == match || drawable->contains(match))
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return true;
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return false;
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkGroup* SkGroup::copy() {
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkGroup* result = new SkGroup();
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    result->fOriginal = this;
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    result->fChildren = fChildren;
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return result;
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkBool SkGroup::copySet(int index) {
818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (fCopies[index >> 5] & 1 << (index & 0x1f)) != 0;
828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDisplayable* SkGroup::deepCopy(SkAnimateMaker* maker) {
858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDisplayable* copy = INHERITED::deepCopy(maker);
86986ca61cf7be3ec590f8820e9b7ba042ac2948fereed    for (SkADrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDisplayable* displayable = (SkDisplayable*)*ptr;
888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDisplayable* deeperCopy = displayable->deepCopy(maker);
891d3c411f5e4d2ad31bc92b3a85957004329ac00dtfarina@chromium.org        ((SkGroup*)copy)->addChild(*maker, deeperCopy);
908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return copy;
928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkGroup::doEvent(SkDisplayEvent::Kind kind, SkEventState* state) {
958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool handled = false;
96986ca61cf7be3ec590f8820e9b7ba042ac2948fereed    for (SkADrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
97986ca61cf7be3ec590f8820e9b7ba042ac2948fereed        SkADrawable* drawable = *ptr;
988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (drawable->isDrawable() == false)
998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            continue;
1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        handled |= drawable->doEvent(kind, state);
1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return handled;
1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkGroup::draw(SkAnimateMaker& maker) {
1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool conditionTrue = ifCondition(maker, this, condition);
1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool result = false;
108986ca61cf7be3ec590f8820e9b7ba042ac2948fereed    for (SkADrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
109986ca61cf7be3ec590f8820e9b7ba042ac2948fereed        SkADrawable* drawable = *ptr;
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (drawable->isDrawable() == false)
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            continue;
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (conditionTrue == false) {
1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (drawable->isApply())
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                ((SkApply*) drawable)->disable();
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            continue;
1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        maker.validate();
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        result |= drawable->draw(maker);
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        maker.validate();
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return result;
1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DUMP_ENABLED
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkGroup::dump(SkAnimateMaker* maker) {
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    dumpBase(maker);
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (condition.size() > 0)
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDebugf("condition=\"%s\" ", condition.c_str());
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (enableCondition.size() > 0)
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDebugf("enableCondition=\"%s\" ", enableCondition.c_str());
1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    dumpDrawables(maker);
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkGroup::dumpDrawables(SkAnimateMaker* maker) {
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDisplayList::fIndent += 4;
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int save = SkDisplayList::fDumpIndex;
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDisplayList::fDumpIndex = 0;
1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool closedYet = false;
139986ca61cf7be3ec590f8820e9b7ba042ac2948fereed    for (SkADrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (closedYet == false) {
1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            closedYet = true;
1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkDebugf(">\n");
1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
144986ca61cf7be3ec590f8820e9b7ba042ac2948fereed        SkADrawable* drawable = *ptr;
1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        drawable->dump(maker);
1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDisplayList::fDumpIndex++;
1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDisplayList::fIndent -= 4;
1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDisplayList::fDumpIndex = save;
1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (closedYet) //we had children, now it's time to close the group
1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dumpEnd(maker);
1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    else    //no children
1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDebugf("/>\n");
1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkGroup::dumpEvents() {
157986ca61cf7be3ec590f8820e9b7ba042ac2948fereed    for (SkADrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
158986ca61cf7be3ec590f8820e9b7ba042ac2948fereed        SkADrawable* drawable = *ptr;
1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        drawable->dumpEvents();
1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkGroup::enable(SkAnimateMaker& maker ) {
1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    reset();
166986ca61cf7be3ec590f8820e9b7ba042ac2948fereed    for (SkADrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
167986ca61cf7be3ec590f8820e9b7ba042ac2948fereed        SkADrawable* drawable = *ptr;
1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (ifCondition(maker, drawable, enableCondition) == false)
1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            continue;
1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        drawable->enable(maker);
1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return true;    // skip add; already added so that scope is findable by children
1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
175986ca61cf7be3ec590f8820e9b7ba042ac2948fereedint SkGroup::findGroup(SkADrawable* match,  SkTDDrawableArray** list,
1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                 SkGroup** parent, SkGroup** found, SkTDDrawableArray** grandList) {
1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    *list = &fChildren;
178986ca61cf7be3ec590f8820e9b7ba042ac2948fereed    for (SkADrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
179986ca61cf7be3ec590f8820e9b7ba042ac2948fereed        SkADrawable* drawable = *ptr;
1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (drawable->isGroup()) {
1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkGroup* childGroup = (SkGroup*) drawable;
1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (childGroup->fOriginal == match)
1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                goto foundMatch;
1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (drawable == match) {
1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comfoundMatch:
1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            *parent = this;
1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return (int) (ptr - fChildren.begin());
1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    *grandList = &fChildren;
1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkDisplayList::SearchForMatch(match, list, parent, found, grandList);
1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkGroup::hasEnable() const {
1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return true;
1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
199986ca61cf7be3ec590f8820e9b7ba042ac2948fereedbool SkGroup::ifCondition(SkAnimateMaker& maker, SkADrawable*,
2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkString& conditionString) {
2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (conditionString.size() == 0)
2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return true;
2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int32_t result;
2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool success = SkAnimatorScript::EvaluateInt(maker, this, conditionString.c_str(), &result);
2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DUMP_ENABLED
2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (maker.fDumpGConditions) {
2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDebugf("group: ");
2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dumpBase(&maker);
2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDebugf("condition=%s ", conditionString.c_str());
2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (success == false)
2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkDebugf("(script failed)\n");
2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        else
2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkDebugf("success=%s\n", result != 0 ? "true" : "false");
2148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return success && result != 0;
2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkGroup::initialize() {
220986ca61cf7be3ec590f8820e9b7ba042ac2948fereed    for (SkADrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
221986ca61cf7be3ec590f8820e9b7ba042ac2948fereed        SkADrawable* drawable = *ptr;
2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (drawable->isDrawable() == false)
2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            continue;
2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        drawable->initialize();
2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkGroup::markCopyClear(int index) {
2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (index < 0)
2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        index = fChildren.count();
2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fCopies[index >> 5] &= ~(1 << (index & 0x1f));
2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkGroup::markCopySet(int index) {
2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (index < 0)
2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        index = fChildren.count();
2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fCopies[index >> 5] |= 1 << (index & 0x1f);
2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkGroup::markCopySize(int index) {
2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (index < 0)
2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        index = fChildren.count() + 1;
2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int oldLongs = fCopies.count();
2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int newLongs = (index >> 5) + 1;
2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (oldLongs < newLongs) {
2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fCopies.setCount(newLongs);
2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        memset(&fCopies[oldLongs], 0, (newLongs - oldLongs) << 2);
2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkGroup::reset() {
2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fOriginal)  // has been copied
2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int index = 0;
2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int max = fCopies.count() << 5;
256986ca61cf7be3ec590f8820e9b7ba042ac2948fereed    for (SkADrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (index >= max || copySet(index) == false)
2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            continue;
2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkApply* apply = (SkApply*) *ptr;
2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(apply->isApply());
2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(apply->getScope());
2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *ptr = apply->getScope();
2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        markCopyClear(index);
2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        index++;
2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkGroup::resolveIDs(SkAnimateMaker& maker, SkDisplayable* orig, SkApply* apply) {
2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkGroup* original = (SkGroup*) orig;
2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkTDDrawableArray& originalChildren = original->fChildren;
271986ca61cf7be3ec590f8820e9b7ba042ac2948fereed    SkADrawable** originalPtr = originalChildren.begin();
272986ca61cf7be3ec590f8820e9b7ba042ac2948fereed    SkADrawable** ptr = fChildren.begin();
273986ca61cf7be3ec590f8820e9b7ba042ac2948fereed    SkADrawable** end = fChildren.end();
274986ca61cf7be3ec590f8820e9b7ba042ac2948fereed    SkADrawable** origChild = ((SkGroup*) orig)->fChildren.begin();
2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (ptr < end) {
276986ca61cf7be3ec590f8820e9b7ba042ac2948fereed        SkADrawable* drawable = *ptr++;
2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        maker.resolveID(drawable, *origChild++);
2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (drawable->resolveIDs(maker, *originalPtr++, apply) == true)
2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return true; // failed
2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return false;
2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkGroup::setSteps(int steps) {
285986ca61cf7be3ec590f8820e9b7ba042ac2948fereed    for (SkADrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
286986ca61cf7be3ec590f8820e9b7ba042ac2948fereed        SkADrawable* drawable = *ptr;
2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (drawable->isDrawable() == false)
2888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            continue;
2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        drawable->setSteps(steps);
2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkGroup::validate() {
295986ca61cf7be3ec590f8820e9b7ba042ac2948fereed    for (SkADrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
296986ca61cf7be3ec590f8820e9b7ba042ac2948fereed        SkADrawable* drawable = *ptr;
2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        drawable->validate();
2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if SK_USE_CONDENSED_INFO == 0
3038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMemberInfo SkSave::fInfo[] = {
3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SK_MEMBER_INHERITED
3068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
3078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comDEFINE_GET_MEMBER(SkSave);
3118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkSave::draw(SkAnimateMaker& maker) {
3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    maker.fCanvas->save();
3148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint* save = maker.fPaint;
3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint local = SkPaint(*maker.fPaint);
3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    maker.fPaint = &local;
3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool result = INHERITED::draw(maker);
3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    maker.fPaint = save;
3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    maker.fCanvas->restore();
3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return result;
3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
322