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 "SkRect.h" 12 #include "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 : 16; 87 uint32_t fFlags : 16; 88 89 typedef SkRefCnt INHERITED; 90 }; 91 92 // Helper for defining attribute getters/setters in subclasses. 93 #define SG_ATTRIBUTE(attr_name, attr_type, attr_container) \ 94 const attr_type& get##attr_name() const { return attr_container; } \ 95 void set##attr_name(const attr_type& v) { \ 96 if (attr_container == v) return; \ 97 attr_container = v; \ 98 this->invalidate(); \ 99 } \ 100 void set##attr_name(attr_type&& v) { \ 101 if (attr_container == v) return; \ 102 attr_container = std::move(v); \ 103 this->invalidate(); \ 104 } 105 106 #define SG_MAPPED_ATTRIBUTE(attr_name, attr_type, attr_container) \ 107 attr_type get##attr_name() const { return attr_container.get##attr_name(); } \ 108 void set##attr_name(const attr_type& v) { \ 109 if (attr_container.get##attr_name() == v) return; \ 110 attr_container.set##attr_name(v); \ 111 this->invalidate(); \ 112 } \ 113 void set##attr_name(attr_type&& v) { \ 114 if (attr_container.get##attr_name() == v) return; \ 115 attr_container.set##attr_name(std::move(v)); \ 116 this->invalidate(); \ 117 } 118 119 } // namespace sksg 120 121 #endif // SkSGNode_DEFINED 122