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 SkSGTransform_DEFINED
9#define SkSGTransform_DEFINED
10
11#include "modules/sksg/include/SkSGEffectNode.h"
12
13class SkM44;
14class SkMatrix;
15
16namespace sksg {
17
18/**
19 * Transformations base class.
20 */
21class Transform : public Node {
22public:
23    // Compose T' = A x B
24    static sk_sp<Transform> MakeConcat(sk_sp<Transform> a, sk_sp<Transform> b);
25
26    // T' = Inv(T)
27    static sk_sp<Transform> MakeInverse(sk_sp<Transform> t);
28
29protected:
30    Transform();
31
32    virtual bool is44() const = 0;
33
34    virtual SkMatrix asMatrix() const = 0;
35    virtual SkM44    asM44   () const = 0;
36
37private:
38    friend class TransformPriv;
39
40    using INHERITED = Node;
41};
42
43/**
44 * Concrete, matrix-backed Transform.
45 *
46 * Supported instantiations: SkMatrix, SkM44.
47 *
48 * Sample use:
49 *
50 *   auto m33 = Matrix<SkMatrix>::Make(SkMatrix::I());
51 *   ...
52 *   m33->setMatrix(SkMatrix::Translate(10, 10));
53 *
54 */
55template <typename T>
56class Matrix final : public Transform {
57public:
58    template <typename = std::enable_if<std::is_same<T, SkMatrix>::value ||
59                                        std::is_same<T, SkM44   >::value>>
60    static sk_sp<Matrix> Make(const T& m) { return sk_sp<Matrix>(new Matrix(m)); }
61
62    SG_ATTRIBUTE(Matrix, T, fMatrix)
63
64protected:
65    explicit Matrix(const T& m) : fMatrix(m) {}
66
67    SkRect onRevalidate(InvalidationController*, const SkMatrix&) override {
68        return SkRect::MakeEmpty();
69    }
70
71    bool is44() const override { return std::is_same<T, SkM44>::value; }
72
73    SkMatrix asMatrix() const override;
74    SkM44    asM44   () const override;
75
76private:
77    T fMatrix;
78
79    using INHERITED = Transform;
80};
81
82/**
83 * Concrete Effect node, binding a Transform to a RenderNode.
84 */
85class TransformEffect final : public EffectNode {
86public:
87    static sk_sp<TransformEffect> Make(sk_sp<RenderNode> child, sk_sp<Transform> transform) {
88        return child && transform
89            ? sk_sp<TransformEffect>(new TransformEffect(std::move(child), std::move(transform)))
90            : nullptr;
91    }
92
93    static sk_sp<TransformEffect> Make(sk_sp<RenderNode> child, const SkMatrix& m) {
94        return Make(std::move(child), Matrix<SkMatrix>::Make(m));
95    }
96
97    ~TransformEffect() override;
98
99    const sk_sp<Transform>& getTransform() const { return fTransform; }
100
101protected:
102    void onRender(SkCanvas*, const RenderContext*) const override;
103    const RenderNode* onNodeAt(const SkPoint&)     const override;
104
105    SkRect onRevalidate(InvalidationController*, const SkMatrix&) override;
106
107private:
108    TransformEffect(sk_sp<RenderNode>, sk_sp<Transform>);
109
110    const sk_sp<Transform> fTransform;
111
112    using INHERITED = EffectNode;
113};
114
115} // namespace sksg
116
117#endif // SkSGTransform_DEFINED
118