• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
bounds()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);
hasInval()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     using INHERITED = SkRefCnt;
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