/* * Copyright 2017 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "modules/sksg/include/SkSGTransform.h" #include "include/core/SkCanvas.h" #include "modules/sksg/src/SkSGTransformPriv.h" namespace sksg { namespace { template class Concat final : public Transform { public: template ::value || std::is_same::value >> Concat(sk_sp a, sk_sp b) : fA(std::move(a)), fB(std::move(b)) { SkASSERT(fA); SkASSERT(fB); this->observeInval(fA); this->observeInval(fB); } ~Concat() override { this->unobserveInval(fA); this->unobserveInval(fB); } protected: SkRect onRevalidate(InvalidationController* ic, const SkMatrix& ctm) override { fA->revalidate(ic, ctm); fB->revalidate(ic, ctm); fComposed.setConcat(TransformPriv::As(fA), TransformPriv::As(fB)); return SkRect::MakeEmpty(); } bool is44() const override { return std::is_same::value; } SkMatrix asMatrix() const override { SkASSERT(!this->hasInval()); return fComposed; } SkMatrix44 asMatrix44() const override { SkASSERT(!this->hasInval()); return fComposed; } private: const sk_sp fA, fB; T fComposed; using INHERITED = Transform; }; template class Inverse final : public Transform { public: template ::value || std::is_same::value >> explicit Inverse(sk_sp t) : fT(std::move(t)) { SkASSERT(fT); this->observeInval(fT); } ~Inverse() override { this->unobserveInval(fT); } protected: SkRect onRevalidate(InvalidationController* ic, const SkMatrix& ctm) override { fT->revalidate(ic, ctm); if (!TransformPriv::As(fT).invert(&fInverted)) { fInverted.reset(); } return SkRect::MakeEmpty(); } bool is44() const override { return std::is_same::value; } SkMatrix asMatrix() const override { SkASSERT(!this->hasInval()); return fInverted; } SkMatrix44 asMatrix44() const override { SkASSERT(!this->hasInval()); return fInverted; } private: const sk_sp fT; T fInverted; using INHERITED = Transform; }; } // namespace // Transform nodes don't generate damage on their own, but via ancestor TransformEffects. Transform::Transform() : INHERITED(kBubbleDamage_Trait) {} sk_sp Transform::MakeConcat(sk_sp a, sk_sp b) { if (!a) { return b; } if (!b) { return a; } return TransformPriv::Is44(a) || TransformPriv::Is44(b) ? sk_sp(new Concat(std::move(a), std::move(b))) : sk_sp(new Concat(std::move(a), std::move(b))); } sk_sp Transform::MakeInverse(sk_sp t) { if (!t) { return nullptr; } return TransformPriv::Is44(t) ? sk_sp(new Inverse(std::move(t))) : sk_sp(new Inverse(std::move(t))); } TransformEffect::TransformEffect(sk_sp child, sk_sp transform) : INHERITED(std::move(child)) , fTransform(std::move(transform)) { this->observeInval(fTransform); } TransformEffect::~TransformEffect() { this->unobserveInval(fTransform); } void TransformEffect::onRender(SkCanvas* canvas, const RenderContext* ctx) const { const auto m = TransformPriv::As(fTransform); SkAutoCanvasRestore acr(canvas, !m.isIdentity()); canvas->concat(m); this->INHERITED::onRender(canvas, ctx); } const RenderNode* TransformEffect::onNodeAt(const SkPoint& p) const { const auto m = TransformPriv::As(fTransform); SkPoint mapped_p; m.mapPoints(&mapped_p, &p, 1); return this->INHERITED::onNodeAt(mapped_p); } SkRect TransformEffect::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) { SkASSERT(this->hasInval()); // We don't care about matrix reval results. fTransform->revalidate(ic, ctm); const auto m = TransformPriv::As(fTransform); auto bounds = this->INHERITED::onRevalidate(ic, SkMatrix::Concat(ctm, m)); m.mapRect(&bounds); return bounds; } } // namespace sksg