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
15class SkCanvas;
16class SkMatrix;
17
18namespace sksg {
19
20class 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 */
31class Node : public SkRefCnt {
32public:
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
37protected:
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
64private:
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