1
2/*
3 * Copyright 2006 The Android Open Source Project
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10#include "SkDisplayList.h"
11#include "SkAnimateActive.h"
12#include "SkAnimateBase.h"
13#include "SkAnimateMaker.h"
14#include "SkDisplayApply.h"
15#include "SkDrawable.h"
16#include "SkDrawGroup.h"
17#include "SkDrawMatrix.h"
18#include "SkInterpolator.h"
19#include "SkTime.h"
20
21SkDisplayList::SkDisplayList() : fDrawBounds(true), fUnionBounds(false), fInTime(0) {
22}
23
24SkDisplayList::~SkDisplayList() {
25}
26
27void SkDisplayList::append(SkActive* active) {
28    *fActiveList.append() = active;
29}
30
31bool SkDisplayList::draw(SkAnimateMaker& maker, SkMSec inTime) {
32    validate();
33    fInTime = inTime;
34    bool result = false;
35    fInvalBounds.setEmpty();
36    if (fDrawList.count()) {
37        for (SkActive** activePtr = fActiveList.begin(); activePtr < fActiveList.end(); activePtr++) {
38            SkActive* active = *activePtr;
39            active->reset();
40        }
41        for (int index = 0; index < fDrawList.count(); index++) {
42            SkDrawable* draw = fDrawList[index];
43            draw->initialize(); // allow matrices to reset themselves
44            SkASSERT(draw->isDrawable());
45            validate();
46            result |= draw->draw(maker);
47        }
48    }
49    validate();
50    return result;
51}
52
53int SkDisplayList::findGroup(SkDrawable* match, SkTDDrawableArray** list,
54        SkGroup** parent, SkGroup** found, SkTDDrawableArray**grandList) {
55    *parent = NULL;
56    *list = &fDrawList;
57    *grandList = &fDrawList;
58    return SearchForMatch(match, list, parent, found, grandList);
59}
60
61void SkDisplayList::hardReset() {
62    fDrawList.reset();
63    fActiveList.reset();
64}
65
66bool SkDisplayList::onIRect(const SkIRect& r) {
67    fBounds = r;
68    return fDrawBounds;
69}
70
71int SkDisplayList::SearchForMatch(SkDrawable* match, SkTDDrawableArray** list,
72        SkGroup** parent, SkGroup** found, SkTDDrawableArray**grandList) {
73    *found = NULL;
74    for (int index = 0; index < (*list)->count(); index++) {
75        SkDrawable* draw = (**list)[index];
76        if (draw == match)
77            return index;
78        if (draw->isApply()) {
79            SkApply* apply = (SkApply*) draw;
80            if (apply->scope == match)
81                return index;
82            if (apply->scope->isGroup() && SearchGroupForMatch(apply->scope, match, list, parent, found, grandList, index))
83                return index;
84            if (apply->mode == SkApply::kMode_create) {
85                for (SkDrawable** ptr = apply->fScopes.begin(); ptr < apply->fScopes.end(); ptr++) {
86                    SkDrawable* scope = *ptr;
87                    if (scope == match)
88                        return index;
89                    //perhaps should call SearchGroupForMatch here as well (on scope)
90                }
91            }
92        }
93        if (draw->isGroup() && SearchGroupForMatch(draw, match, list, parent, found, grandList, index))
94            return index;
95
96    }
97    return -1;
98}
99
100bool SkDisplayList::SearchGroupForMatch(SkDrawable* draw, SkDrawable* match, SkTDDrawableArray** list,
101        SkGroup** parent, SkGroup** found, SkTDDrawableArray** grandList, int &index) {
102            SkGroup* group = (SkGroup*) draw;
103            if (group->getOriginal() == match)
104                return true;
105            SkTDDrawableArray* saveList = *list;
106            int groupIndex = group->findGroup(match, list, parent, found, grandList);
107            if (groupIndex >= 0) {
108                *found = group;
109                index = groupIndex;
110                return true;
111            }
112            *list = saveList;
113            return false;
114        }
115
116void SkDisplayList::reset() {
117    for (int index = 0; index < fDrawList.count(); index++) {
118        SkDrawable* draw = fDrawList[index];
119        if (draw->isApply() == false)
120            continue;
121        SkApply* apply = (SkApply*) draw;
122        apply->reset();
123    }
124}
125
126void SkDisplayList::remove(SkActive* active) {
127    int index = fActiveList.find(active);
128    SkASSERT(index >= 0);
129    fActiveList.remove(index);  // !!! could use shuffle instead
130    SkASSERT(fActiveList.find(active) < 0);
131}
132
133#ifdef SK_DUMP_ENABLED
134int SkDisplayList::fDumpIndex;
135int SkDisplayList::fIndent;
136
137void SkDisplayList::dump(SkAnimateMaker* maker) {
138    fIndent = 0;
139    dumpInner(maker);
140}
141
142void SkDisplayList::dumpInner(SkAnimateMaker* maker) {
143    for (int index = 0; index < fDrawList.count(); index++) {
144        fDumpIndex = index;
145        fDrawList[fDumpIndex]->dump(maker);
146    }
147}
148
149#endif
150
151#ifdef SK_DEBUG
152void SkDisplayList::validate() {
153    for (int index = 0; index < fDrawList.count(); index++) {
154        SkDrawable* draw = fDrawList[index];
155        draw->validate();
156    }
157}
158#endif
159