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