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 45 explicit Node(uint32_t invalTraits); 46 ~Node() override; 47 48 const SkRect& bounds() const { 49 SkASSERT(!this->hasInval()); 50 return fBounds; 51 } 52 53 // Tag this node for invalidation and optional damage. 54 void invalidate(bool damage = true); 55 bool hasInval() const { return fFlags & kInvalidated_Flag; } 56 57 // Dispatched on revalidation. Subclasses are expected to recompute/cache their properties 58 // and return their bounding box in local coordinates. 59 virtual SkRect onRevalidate(InvalidationController*, const SkMatrix& ctm) = 0; 60 61 // Register/unregister |this| to receive invalidation events from a descendant. 62 void observeInval(const sk_sp<Node>&); 63 void unobserveInval(const sk_sp<Node>&); 64 65 private: 66 enum Flags { 67 kInvalidated_Flag = 1 << 0, // the node or its descendants require revalidation 68 kDamage_Flag = 1 << 1, // the node contributes damage during revalidation 69 kObserverArray_Flag = 1 << 2, // the node has more than one inval observer 70 kInTraversal_Flag = 1 << 3, // the node is part of a traversal (cycle detection) 71 }; 72 73 template <typename Func> 74 void forEachInvalObserver(Func&&) const; 75 76 class ScopedFlag; 77 78 union { 79 Node* fInvalObserver; 80 std::vector<Node*>* fInvalObserverArray; 81 }; 82 SkRect fBounds; 83 const uint32_t fInvalTraits : 16; 84 uint32_t fFlags : 16; 85 86 typedef SkRefCnt INHERITED; 87 }; 88 89 // Helper for defining attribute getters/setters in subclasses. 90 #define SG_ATTRIBUTE(attr_name, attr_type, attr_container) \ 91 const attr_type& get##attr_name() const { return attr_container; } \ 92 void set##attr_name(const attr_type& v) { \ 93 if (attr_container == v) return; \ 94 attr_container = v; \ 95 this->invalidate(); \ 96 } \ 97 void set##attr_name(attr_type&& v) { \ 98 if (attr_container == v) return; \ 99 attr_container = std::move(v); \ 100 this->invalidate(); \ 101 } 102 103 #define SG_MAPPED_ATTRIBUTE(attr_name, attr_type, attr_container) \ 104 attr_type get##attr_name() const { return attr_container.get##attr_name(); } \ 105 void set##attr_name(const attr_type& v) { \ 106 if (attr_container.get##attr_name() == v) return; \ 107 attr_container.set##attr_name(v); \ 108 this->invalidate(); \ 109 } \ 110 void set##attr_name(attr_type&& v) { \ 111 if (attr_container.get##attr_name() == v) return; \ 112 attr_container.set##attr_name(std::move(v)); \ 113 this->invalidate(); \ 114 } 115 116 } // namespace sksg 117 118 #endif // SkSGNode_DEFINED 119