1 | /* |
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 | #ifndef SkSGNode_DEFINED |
9 | #define SkSGNode_DEFINED |
10 | |
11 | #include "include/core/SkRect.h" |
12 | #include "include/core/SkRefCnt.h" |
13 | |
14 | #include <vector> |
15 | |
16 | class SkCanvas; |
17 | class SkMatrix; |
18 | |
19 | namespace sksg { |
20 | |
21 | class InvalidationController; |
22 | |
23 | /** |
24 | * Base class for all scene graph nodes. |
25 | * |
26 | * Handles ingress edge management for the DAG (i.e. node -> "parent" node mapping), |
27 | * and invalidation. |
28 | * |
29 | * Note: egress edges are only implemented/supported in container subclasses |
30 | * (e.g. Group, Effect, Draw). |
31 | */ |
32 | class Node : public SkRefCnt { |
33 | public: |
34 | // Traverse the DAG and revalidate any dependant/invalidated nodes. |
35 | // Returns the bounding box for the DAG fragment. |
36 | const SkRect& revalidate(InvalidationController*, const SkMatrix&); |
37 | |
38 | protected: |
39 | enum InvalTraits { |
40 | // Nodes with this trait never generate direct damage -- instead, |
41 | // the damage bubbles up to ancestors. |
42 | kBubbleDamage_Trait = 1 << 0, |
43 | |
44 | // Nodes with this trait obscure the descendants' damage and always override it. |
45 | kOverrideDamage_Trait = 1 << 1, |
46 | }; |
47 | |
48 | explicit Node(uint32_t invalTraits); |
49 | ~Node() override; |
50 | |
51 | const SkRect& bounds() const { |
52 | SkASSERT(!this->hasInval()); |
53 | return fBounds; |
54 | } |
55 | |
56 | // Tag this node for invalidation and optional damage. |
57 | void invalidate(bool damage = true); |
58 | bool hasInval() const { return fFlags & kInvalidated_Flag; } |
59 | |
60 | // Dispatched on revalidation. Subclasses are expected to recompute/cache their properties |
61 | // and return their bounding box in local coordinates. |
62 | virtual SkRect onRevalidate(InvalidationController*, const SkMatrix& ctm) = 0; |
63 | |
64 | // Register/unregister |this| to receive invalidation events from a descendant. |
65 | void observeInval(const sk_sp<Node>&); |
66 | void unobserveInval(const sk_sp<Node>&); |
67 | |
68 | private: |
69 | enum Flags { |
70 | kInvalidated_Flag = 1 << 0, // the node or its descendants require revalidation |
71 | kDamage_Flag = 1 << 1, // the node contributes damage during revalidation |
72 | kObserverArray_Flag = 1 << 2, // the node has more than one inval observer |
73 | kInTraversal_Flag = 1 << 3, // the node is part of a traversal (cycle detection) |
74 | }; |
75 | |
76 | template <typename Func> |
77 | void forEachInvalObserver(Func&&) const; |
78 | |
79 | class ScopedFlag; |
80 | |
81 | union { |
82 | Node* fInvalObserver; |
83 | std::vector<Node*>* fInvalObserverArray; |
84 | }; |
85 | SkRect fBounds; |
86 | const uint32_t fInvalTraits : 2; |
87 | uint32_t fFlags : 4; // Internal flags. |
88 | uint32_t fNodeFlags : 8; // Accessible from select subclasses. |
89 | // Free bits : 18; |
90 | |
91 | friend class NodePriv; |
92 | friend class RenderNode; // node flags access |
93 | |
94 | typedef SkRefCnt INHERITED; |
95 | }; |
96 | |
97 | // Helper for defining attribute getters/setters in subclasses. |
98 | #define SG_ATTRIBUTE(attr_name, attr_type, attr_container) \ |
99 | const attr_type& get##attr_name() const { return attr_container; } \ |
100 | void set##attr_name(const attr_type& v) { \ |
101 | if (attr_container == v) return; \ |
102 | attr_container = v; \ |
103 | this->invalidate(); \ |
104 | } \ |
105 | void set##attr_name(attr_type&& v) { \ |
106 | if (attr_container == v) return; \ |
107 | attr_container = std::move(v); \ |
108 | this->invalidate(); \ |
109 | } |
110 | |
111 | #define SG_MAPPED_ATTRIBUTE(attr_name, attr_type, attr_container) \ |
112 | attr_type get##attr_name() const { return attr_container.get##attr_name(); } \ |
113 | void set##attr_name(const attr_type& v) { \ |
114 | if (attr_container.get##attr_name() == v) return; \ |
115 | attr_container.set##attr_name(v); \ |
116 | this->invalidate(); \ |
117 | } \ |
118 | void set##attr_name(attr_type&& v) { \ |
119 | if (attr_container.get##attr_name() == v) return; \ |
120 | attr_container.set##attr_name(std::move(v)); \ |
121 | this->invalidate(); \ |
122 | } |
123 | |
124 | } // namespace sksg |
125 | |
126 | #endif // SkSGNode_DEFINED |
127 | |