• 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 class Concat final : public Transform {
19 public:
20     template <typename = std::enable_if<std::is_same<T, SkMatrix  >::value ||
21                                         std::is_same<T, SkMatrix44>::value >>
Concat(sk_sp<Transform> a,sk_sp<Transform> b)22     Concat(sk_sp<Transform> a, sk_sp<Transform> b)
23         : fA(std::move(a)), fB(std::move(b)) {
24         SkASSERT(fA);
25         SkASSERT(fB);
26 
27         this->observeInval(fA);
28         this->observeInval(fB);
29     }
30 
~Concat()31     ~Concat() override {
32         this->unobserveInval(fA);
33         this->unobserveInval(fB);
34     }
35 
36 protected:
onRevalidate(InvalidationController * ic,const SkMatrix & ctm)37     SkRect onRevalidate(InvalidationController* ic, const SkMatrix& ctm) override {
38         fA->revalidate(ic, ctm);
39         fB->revalidate(ic, ctm);
40 
41         fComposed.setConcat(TransformPriv::As<T>(fA),
42                             TransformPriv::As<T>(fB));
43         return SkRect::MakeEmpty();
44     }
45 
is44() const46     bool is44() const override { return std::is_same<T, SkMatrix44>::value; }
47 
asMatrix() const48     SkMatrix asMatrix() const override {
49         SkASSERT(!this->hasInval());
50         return fComposed;
51     }
52 
asMatrix44() const53     SkMatrix44 asMatrix44() const override {
54         SkASSERT(!this->hasInval());
55         return fComposed;
56     }
57 
58 private:
59     const sk_sp<Transform> fA, fB;
60     T                      fComposed;
61 
62     using INHERITED = Transform;
63 };
64 
65 template <typename T>
66 class Inverse final : public Transform {
67 public:
68     template <typename = std::enable_if<std::is_same<T, SkMatrix  >::value ||
69                                         std::is_same<T, SkMatrix44>::value >>
Inverse(sk_sp<Transform> t)70     explicit Inverse(sk_sp<Transform> t)
71         : fT(std::move(t)) {
72         SkASSERT(fT);
73 
74         this->observeInval(fT);
75     }
76 
~Inverse()77     ~Inverse() override {
78         this->unobserveInval(fT);
79     }
80 
81 protected:
onRevalidate(InvalidationController * ic,const SkMatrix & ctm)82     SkRect onRevalidate(InvalidationController* ic, const SkMatrix& ctm) override {
83         fT->revalidate(ic, ctm);
84 
85         if (!TransformPriv::As<T>(fT).invert(&fInverted)) {
86             fInverted.reset();
87         }
88 
89         return SkRect::MakeEmpty();
90     }
91 
is44() const92     bool is44() const override { return std::is_same<T, SkMatrix44>::value; }
93 
asMatrix() const94     SkMatrix asMatrix() const override {
95         SkASSERT(!this->hasInval());
96         return fInverted;
97     }
98 
asMatrix44() const99     SkMatrix44 asMatrix44() const override {
100         SkASSERT(!this->hasInval());
101         return fInverted;
102     }
103 
104 private:
105     const sk_sp<Transform> fT;
106     T                      fInverted;
107 
108     using INHERITED = Transform;
109 };
110 
111 } // namespace
112 
113 // Transform nodes don't generate damage on their own, but via ancestor TransformEffects.
Transform()114 Transform::Transform() : INHERITED(kBubbleDamage_Trait) {}
115 
MakeConcat(sk_sp<Transform> a,sk_sp<Transform> b)116 sk_sp<Transform> Transform::MakeConcat(sk_sp<Transform> a, sk_sp<Transform> b) {
117     if (!a) {
118         return b;
119     }
120 
121     if (!b) {
122         return a;
123     }
124 
125     return TransformPriv::Is44(a) || TransformPriv::Is44(b)
126         ? sk_sp<Transform>(new Concat<SkMatrix44>(std::move(a), std::move(b)))
127         : sk_sp<Transform>(new Concat<SkMatrix  >(std::move(a), std::move(b)));
128 }
129 
MakeInverse(sk_sp<Transform> t)130 sk_sp<Transform> Transform::MakeInverse(sk_sp<Transform> t) {
131     if (!t) {
132         return nullptr;
133     }
134 
135     return TransformPriv::Is44(t)
136         ? sk_sp<Transform>(new Inverse<SkMatrix44>(std::move(t)))
137         : sk_sp<Transform>(new Inverse<SkMatrix  >(std::move(t)));
138 }
139 
TransformEffect(sk_sp<RenderNode> child,sk_sp<Transform> transform)140 TransformEffect::TransformEffect(sk_sp<RenderNode> child, sk_sp<Transform> transform)
141     : INHERITED(std::move(child))
142     , fTransform(std::move(transform)) {
143     this->observeInval(fTransform);
144 }
145 
~TransformEffect()146 TransformEffect::~TransformEffect() {
147     this->unobserveInval(fTransform);
148 }
149 
onRender(SkCanvas * canvas,const RenderContext * ctx) const150 void TransformEffect::onRender(SkCanvas* canvas, const RenderContext* ctx) const {
151     const auto m = TransformPriv::As<SkMatrix>(fTransform);
152     SkAutoCanvasRestore acr(canvas, !m.isIdentity());
153     canvas->concat(m);
154     this->INHERITED::onRender(canvas, ctx);
155 }
156 
onNodeAt(const SkPoint & p) const157 const RenderNode* TransformEffect::onNodeAt(const SkPoint& p) const {
158     const auto m = TransformPriv::As<SkMatrix>(fTransform);
159 
160     SkPoint mapped_p;
161     m.mapPoints(&mapped_p, &p, 1);
162 
163     return this->INHERITED::onNodeAt(mapped_p);
164 }
165 
onRevalidate(InvalidationController * ic,const SkMatrix & ctm)166 SkRect TransformEffect::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) {
167     SkASSERT(this->hasInval());
168 
169     // We don't care about matrix reval results.
170     fTransform->revalidate(ic, ctm);
171 
172     const auto m = TransformPriv::As<SkMatrix>(fTransform);
173     auto bounds = this->INHERITED::onRevalidate(ic, SkMatrix::Concat(ctm, m));
174     m.mapRect(&bounds);
175 
176     return bounds;
177 }
178 
179 } // namespace sksg
180