blob: 3b404edd50b5603b6eedf70749a1c78337ba681d [file] [log] [blame]
Florin Malita4aa44412017-12-19 12:21:02 -05001/*
2 * Copyright 2017 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkSGNode.h"
9
10namespace sksg {
11
12class Node::ScopedFlag {
13public:
14 ScopedFlag(Node* node, uint32_t flag)
15 : fNode(node)
16 , fFlag(flag) {
17 SkASSERT(!(fNode->fFlags & fFlag));
18 fNode->fFlags |= fFlag;
19 }
20 ~ScopedFlag() {
21 fNode->fFlags &= ~fFlag;;
22 }
23
24private:
25 Node* fNode;
26 uint32_t fFlag;
27};
28
29#define TRAVERSAL_GUARD \
30 if (this->fFlags & kInTraversal_Flag) { \
31 return; \
32 } \
33 ScopedFlag traversal_guard(this, kInTraversal_Flag);
34
35Node::Node()
36 : fInvalReceiver(nullptr)
37 , fFlags(kInvalidated_Flag) {}
38
39Node::~Node() {
40 if (fFlags & kReceiverArray_Flag) {
41 SkASSERT(fInvalReceiverArray->isEmpty());
42 delete fInvalReceiverArray;
43 } else {
44 SkASSERT(!fInvalReceiver);
45 }
46}
47
48void Node::addInvalReceiver(Node* receiver) {
49 if (!(fFlags & kReceiverArray_Flag)) {
50 if (!fInvalReceiver) {
51 fInvalReceiver = receiver;
52 return;
53 }
54
55 auto receivers = new SkTDArray<Node*>();
56 receivers->setReserve(2);
57 receivers->push(fInvalReceiver);
58
59 fInvalReceiverArray = receivers;
60 fFlags |= kReceiverArray_Flag;
61 }
62
63 // No duplicate receivers.
64 SkASSERT(fInvalReceiverArray->find(receiver) < 0);
65
66 fInvalReceiverArray->push(receiver);
67}
68
69void Node::removeInvalReceiver(Node* receiver) {
70 if (!(fFlags & kReceiverArray_Flag)) {
71 SkASSERT(fInvalReceiver == receiver);
72 fInvalReceiver = nullptr;
73 return;
74 }
75
76 const auto idx = fInvalReceiverArray->find(receiver);
77 SkASSERT(idx >= 0);
78 fInvalReceiverArray->remove(idx);
79}
80
81template <typename Func>
82void Node::forEachInvalReceiver(Func&& func) const {
83 if (fFlags & kReceiverArray_Flag) {
84 for (const auto& parent : *fInvalReceiverArray) {
85 func(parent);
86 }
87 return;
88 }
89
90 if (fInvalReceiver) {
91 func(fInvalReceiver);
92 }
93}
94
95void Node::invalidate() {
96 TRAVERSAL_GUARD
97
98 if (this->isInvalidated()) {
99 return;
100 }
101
102 fFlags |= kInvalidated_Flag;
103 forEachInvalReceiver([&](Node* receiver) {
104 receiver->invalidate();
105 });
106}
107
108void Node::revalidate(InvalidationController* ic, const SkMatrix& ctm) {
109 TRAVERSAL_GUARD
110
111 if (this->isInvalidated()) {
112 this->onRevalidate(ic, ctm);
113 fFlags &= ~kInvalidated_Flag;
114 }
115}
116
117} // namespace sksg