/* * 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 "SkSGTransform.h" #include "SkCanvas.h" #include "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 { return fComposed; } SkMatrix44 asMatrix44() const override { return fComposed; } private: const sk_sp fA, fB; T fComposed; 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))); } 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