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 "SkSGTransform.h"
9
10 #include "SkCanvas.h"
11 #include "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 return fComposed;
50 }
51
asMatrix44() const52 SkMatrix44 asMatrix44() const override {
53 return fComposed;
54 }
55
56 private:
57 const sk_sp<Transform> fA, fB;
58 T fComposed;
59
60 using INHERITED = Transform;
61 };
62
63 } // namespace
64
65 // Transform nodes don't generate damage on their own, but via ancestor TransformEffects.
Transform()66 Transform::Transform() : INHERITED(kBubbleDamage_Trait) {}
67
MakeConcat(sk_sp<Transform> a,sk_sp<Transform> b)68 sk_sp<Transform> Transform::MakeConcat(sk_sp<Transform> a, sk_sp<Transform> b) {
69 if (!a) {
70 return b;
71 }
72
73 if (!b) {
74 return a;
75 }
76
77 return TransformPriv::Is44(a) || TransformPriv::Is44(b)
78 ? sk_sp<Transform>(new Concat<SkMatrix44>(std::move(a), std::move(b)))
79 : sk_sp<Transform>(new Concat<SkMatrix >(std::move(a), std::move(b)));
80 }
81
TransformEffect(sk_sp<RenderNode> child,sk_sp<Transform> transform)82 TransformEffect::TransformEffect(sk_sp<RenderNode> child, sk_sp<Transform> transform)
83 : INHERITED(std::move(child))
84 , fTransform(std::move(transform)) {
85 this->observeInval(fTransform);
86 }
87
~TransformEffect()88 TransformEffect::~TransformEffect() {
89 this->unobserveInval(fTransform);
90 }
91
onRender(SkCanvas * canvas,const RenderContext * ctx) const92 void TransformEffect::onRender(SkCanvas* canvas, const RenderContext* ctx) const {
93 const auto m = TransformPriv::As<SkMatrix>(fTransform);
94 SkAutoCanvasRestore acr(canvas, !m.isIdentity());
95 canvas->concat(m);
96 this->INHERITED::onRender(canvas, ctx);
97 }
98
onNodeAt(const SkPoint & p) const99 const RenderNode* TransformEffect::onNodeAt(const SkPoint& p) const {
100 const auto m = TransformPriv::As<SkMatrix>(fTransform);
101
102 SkPoint mapped_p;
103 m.mapPoints(&mapped_p, &p, 1);
104
105 return this->INHERITED::onNodeAt(mapped_p);
106 }
107
onRevalidate(InvalidationController * ic,const SkMatrix & ctm)108 SkRect TransformEffect::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) {
109 SkASSERT(this->hasInval());
110
111 // We don't care about matrix reval results.
112 fTransform->revalidate(ic, ctm);
113
114 const auto m = TransformPriv::As<SkMatrix>(fTransform);
115 auto bounds = this->INHERITED::onRevalidate(ic, SkMatrix::Concat(ctm, m));
116 m.mapRect(&bounds);
117
118 return bounds;
119 }
120
121 } // namespace sksg
122