Home | History | Annotate | Download | only in include
      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