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