1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2017 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "modules/sksg/include/SkSGTransform.h"
9cb93a386Sopenharmony_ci
10cb93a386Sopenharmony_ci#include "include/core/SkCanvas.h"
11cb93a386Sopenharmony_ci#include "modules/sksg/src/SkSGTransformPriv.h"
12cb93a386Sopenharmony_ci
13cb93a386Sopenharmony_cinamespace sksg {
14cb93a386Sopenharmony_ci
15cb93a386Sopenharmony_cinamespace {
16cb93a386Sopenharmony_ci
17cb93a386Sopenharmony_citemplate <typename T>
18cb93a386Sopenharmony_ciSkMatrix AsSkMatrix(const T&);
19cb93a386Sopenharmony_ci
20cb93a386Sopenharmony_citemplate <>
21cb93a386Sopenharmony_ciSkMatrix AsSkMatrix<SkMatrix>(const SkMatrix& m) { return m; }
22cb93a386Sopenharmony_ci
23cb93a386Sopenharmony_citemplate <>
24cb93a386Sopenharmony_ciSkMatrix AsSkMatrix<SkM44>(const SkM44& m) { return m.asM33(); }
25cb93a386Sopenharmony_ci
26cb93a386Sopenharmony_citemplate <typename T>
27cb93a386Sopenharmony_ciSkM44 AsSkM44(const T&);
28cb93a386Sopenharmony_ci
29cb93a386Sopenharmony_citemplate <>
30cb93a386Sopenharmony_ciSkM44 AsSkM44<SkMatrix>(const SkMatrix& m) { return SkM44(m); }
31cb93a386Sopenharmony_ci
32cb93a386Sopenharmony_citemplate <>
33cb93a386Sopenharmony_ciSkM44 AsSkM44<SkM44>(const SkM44& m) { return m; }
34cb93a386Sopenharmony_ci
35cb93a386Sopenharmony_citemplate <typename T>
36cb93a386Sopenharmony_ciclass Concat final : public Transform {
37cb93a386Sopenharmony_cipublic:
38cb93a386Sopenharmony_ci    template <typename = std::enable_if<std::is_same<T, SkMatrix>::value ||
39cb93a386Sopenharmony_ci                                        std::is_same<T, SkM44   >::value >>
40cb93a386Sopenharmony_ci    Concat(sk_sp<Transform> a, sk_sp<Transform> b)
41cb93a386Sopenharmony_ci        : fA(std::move(a)), fB(std::move(b)) {
42cb93a386Sopenharmony_ci        SkASSERT(fA);
43cb93a386Sopenharmony_ci        SkASSERT(fB);
44cb93a386Sopenharmony_ci
45cb93a386Sopenharmony_ci        this->observeInval(fA);
46cb93a386Sopenharmony_ci        this->observeInval(fB);
47cb93a386Sopenharmony_ci    }
48cb93a386Sopenharmony_ci
49cb93a386Sopenharmony_ci    ~Concat() override {
50cb93a386Sopenharmony_ci        this->unobserveInval(fA);
51cb93a386Sopenharmony_ci        this->unobserveInval(fB);
52cb93a386Sopenharmony_ci    }
53cb93a386Sopenharmony_ci
54cb93a386Sopenharmony_ciprotected:
55cb93a386Sopenharmony_ci    SkRect onRevalidate(InvalidationController* ic, const SkMatrix& ctm) override {
56cb93a386Sopenharmony_ci        fA->revalidate(ic, ctm);
57cb93a386Sopenharmony_ci        fB->revalidate(ic, ctm);
58cb93a386Sopenharmony_ci
59cb93a386Sopenharmony_ci        fComposed.setConcat(TransformPriv::As<T>(fA),
60cb93a386Sopenharmony_ci                            TransformPriv::As<T>(fB));
61cb93a386Sopenharmony_ci        return SkRect::MakeEmpty();
62cb93a386Sopenharmony_ci    }
63cb93a386Sopenharmony_ci
64cb93a386Sopenharmony_ci    bool is44() const override { return std::is_same<T, SkM44>::value; }
65cb93a386Sopenharmony_ci
66cb93a386Sopenharmony_ci    SkMatrix asMatrix() const override {
67cb93a386Sopenharmony_ci        SkASSERT(!this->hasInval());
68cb93a386Sopenharmony_ci        return AsSkMatrix(fComposed);
69cb93a386Sopenharmony_ci    }
70cb93a386Sopenharmony_ci
71cb93a386Sopenharmony_ci    SkM44 asM44() const override {
72cb93a386Sopenharmony_ci        SkASSERT(!this->hasInval());
73cb93a386Sopenharmony_ci        return AsSkM44(fComposed);
74cb93a386Sopenharmony_ci    }
75cb93a386Sopenharmony_ci
76cb93a386Sopenharmony_ciprivate:
77cb93a386Sopenharmony_ci    const sk_sp<Transform> fA, fB;
78cb93a386Sopenharmony_ci    T                      fComposed;
79cb93a386Sopenharmony_ci
80cb93a386Sopenharmony_ci    using INHERITED = Transform;
81cb93a386Sopenharmony_ci};
82cb93a386Sopenharmony_ci
83cb93a386Sopenharmony_citemplate <typename T>
84cb93a386Sopenharmony_ciclass Inverse final : public Transform {
85cb93a386Sopenharmony_cipublic:
86cb93a386Sopenharmony_ci    template <typename = std::enable_if<std::is_same<T, SkMatrix>::value ||
87cb93a386Sopenharmony_ci                                        std::is_same<T, SkM44   >::value >>
88cb93a386Sopenharmony_ci    explicit Inverse(sk_sp<Transform> t)
89cb93a386Sopenharmony_ci        : fT(std::move(t)) {
90cb93a386Sopenharmony_ci        SkASSERT(fT);
91cb93a386Sopenharmony_ci
92cb93a386Sopenharmony_ci        this->observeInval(fT);
93cb93a386Sopenharmony_ci    }
94cb93a386Sopenharmony_ci
95cb93a386Sopenharmony_ci    ~Inverse() override {
96cb93a386Sopenharmony_ci        this->unobserveInval(fT);
97cb93a386Sopenharmony_ci    }
98cb93a386Sopenharmony_ci
99cb93a386Sopenharmony_ciprotected:
100cb93a386Sopenharmony_ci    SkRect onRevalidate(InvalidationController* ic, const SkMatrix& ctm) override {
101cb93a386Sopenharmony_ci        fT->revalidate(ic, ctm);
102cb93a386Sopenharmony_ci
103cb93a386Sopenharmony_ci        if (!TransformPriv::As<T>(fT).invert(&fInverted)) {
104cb93a386Sopenharmony_ci            fInverted.setIdentity();
105cb93a386Sopenharmony_ci        }
106cb93a386Sopenharmony_ci
107cb93a386Sopenharmony_ci        return SkRect::MakeEmpty();
108cb93a386Sopenharmony_ci    }
109cb93a386Sopenharmony_ci
110cb93a386Sopenharmony_ci    bool is44() const override { return std::is_same<T, SkM44>::value; }
111cb93a386Sopenharmony_ci
112cb93a386Sopenharmony_ci    SkMatrix asMatrix() const override {
113cb93a386Sopenharmony_ci        SkASSERT(!this->hasInval());
114cb93a386Sopenharmony_ci        return AsSkMatrix(fInverted);
115cb93a386Sopenharmony_ci    }
116cb93a386Sopenharmony_ci
117cb93a386Sopenharmony_ci    SkM44 asM44() const override {
118cb93a386Sopenharmony_ci        SkASSERT(!this->hasInval());
119cb93a386Sopenharmony_ci        return AsSkM44(fInverted);
120cb93a386Sopenharmony_ci    }
121cb93a386Sopenharmony_ci
122cb93a386Sopenharmony_ciprivate:
123cb93a386Sopenharmony_ci    const sk_sp<Transform> fT;
124cb93a386Sopenharmony_ci    T                      fInverted;
125cb93a386Sopenharmony_ci
126cb93a386Sopenharmony_ci    using INHERITED = Transform;
127cb93a386Sopenharmony_ci};
128cb93a386Sopenharmony_ci
129cb93a386Sopenharmony_ci} // namespace
130cb93a386Sopenharmony_ci
131cb93a386Sopenharmony_citemplate <>
132cb93a386Sopenharmony_ciSkMatrix Matrix<SkMatrix>::asMatrix() const { return fMatrix; }
133cb93a386Sopenharmony_ci
134cb93a386Sopenharmony_citemplate <>
135cb93a386Sopenharmony_ciSkM44 Matrix<SkMatrix>::asM44() const { return SkM44(fMatrix); }
136cb93a386Sopenharmony_ci
137cb93a386Sopenharmony_citemplate <>
138cb93a386Sopenharmony_ciSkMatrix Matrix<SkM44>::asMatrix() const { return fMatrix.asM33(); }
139cb93a386Sopenharmony_ci
140cb93a386Sopenharmony_citemplate <>
141cb93a386Sopenharmony_ciSkM44 Matrix<SkM44>::asM44() const { return fMatrix; }
142cb93a386Sopenharmony_ci
143cb93a386Sopenharmony_ci// Transform nodes don't generate damage on their own, but via ancestor TransformEffects.
144cb93a386Sopenharmony_ciTransform::Transform() : INHERITED(kBubbleDamage_Trait) {}
145cb93a386Sopenharmony_ci
146cb93a386Sopenharmony_cisk_sp<Transform> Transform::MakeConcat(sk_sp<Transform> a, sk_sp<Transform> b) {
147cb93a386Sopenharmony_ci    if (!a) {
148cb93a386Sopenharmony_ci        return b;
149cb93a386Sopenharmony_ci    }
150cb93a386Sopenharmony_ci
151cb93a386Sopenharmony_ci    if (!b) {
152cb93a386Sopenharmony_ci        return a;
153cb93a386Sopenharmony_ci    }
154cb93a386Sopenharmony_ci
155cb93a386Sopenharmony_ci    return TransformPriv::Is44(a) || TransformPriv::Is44(b)
156cb93a386Sopenharmony_ci        ? sk_sp<Transform>(new Concat<SkM44   >(std::move(a), std::move(b)))
157cb93a386Sopenharmony_ci        : sk_sp<Transform>(new Concat<SkMatrix>(std::move(a), std::move(b)));
158cb93a386Sopenharmony_ci}
159cb93a386Sopenharmony_ci
160cb93a386Sopenharmony_cisk_sp<Transform> Transform::MakeInverse(sk_sp<Transform> t) {
161cb93a386Sopenharmony_ci    if (!t) {
162cb93a386Sopenharmony_ci        return nullptr;
163cb93a386Sopenharmony_ci    }
164cb93a386Sopenharmony_ci
165cb93a386Sopenharmony_ci    return TransformPriv::Is44(t)
166cb93a386Sopenharmony_ci        ? sk_sp<Transform>(new Inverse<SkM44   >(std::move(t)))
167cb93a386Sopenharmony_ci        : sk_sp<Transform>(new Inverse<SkMatrix>(std::move(t)));
168cb93a386Sopenharmony_ci}
169cb93a386Sopenharmony_ci
170cb93a386Sopenharmony_ciTransformEffect::TransformEffect(sk_sp<RenderNode> child, sk_sp<Transform> transform)
171cb93a386Sopenharmony_ci    : INHERITED(std::move(child))
172cb93a386Sopenharmony_ci    , fTransform(std::move(transform)) {
173cb93a386Sopenharmony_ci    this->observeInval(fTransform);
174cb93a386Sopenharmony_ci}
175cb93a386Sopenharmony_ci
176cb93a386Sopenharmony_ciTransformEffect::~TransformEffect() {
177cb93a386Sopenharmony_ci    this->unobserveInval(fTransform);
178cb93a386Sopenharmony_ci}
179cb93a386Sopenharmony_ci
180cb93a386Sopenharmony_civoid TransformEffect::onRender(SkCanvas* canvas, const RenderContext* ctx) const {
181cb93a386Sopenharmony_ci    SkAutoCanvasRestore acr(canvas, true);
182cb93a386Sopenharmony_ci    canvas->concat(TransformPriv::As<SkM44>(fTransform));
183cb93a386Sopenharmony_ci
184cb93a386Sopenharmony_ci    this->INHERITED::onRender(canvas, ctx);
185cb93a386Sopenharmony_ci}
186cb93a386Sopenharmony_ci
187cb93a386Sopenharmony_ciconst RenderNode* TransformEffect::onNodeAt(const SkPoint& p) const {
188cb93a386Sopenharmony_ci    const auto p4 = TransformPriv::As<SkM44>(fTransform).map(p.fX, p.fY, 0, 0);
189cb93a386Sopenharmony_ci
190cb93a386Sopenharmony_ci    return this->INHERITED::onNodeAt({p4.x, p4.y});
191cb93a386Sopenharmony_ci}
192cb93a386Sopenharmony_ci
193cb93a386Sopenharmony_ciSkRect TransformEffect::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) {
194cb93a386Sopenharmony_ci    SkASSERT(this->hasInval());
195cb93a386Sopenharmony_ci
196cb93a386Sopenharmony_ci    // We don't care about matrix reval results.
197cb93a386Sopenharmony_ci    fTransform->revalidate(ic, ctm);
198cb93a386Sopenharmony_ci
199cb93a386Sopenharmony_ci    // TODO: need to update all the reval plumbing for m44.
200cb93a386Sopenharmony_ci    const auto m = TransformPriv::As<SkMatrix>(fTransform);
201cb93a386Sopenharmony_ci    auto bounds = this->INHERITED::onRevalidate(ic, SkMatrix::Concat(ctm, m));
202cb93a386Sopenharmony_ci    m.mapRect(&bounds);
203cb93a386Sopenharmony_ci
204cb93a386Sopenharmony_ci    return bounds;
205cb93a386Sopenharmony_ci}
206cb93a386Sopenharmony_ci
207cb93a386Sopenharmony_ci} // namespace sksg
208