blob: e869c3a476b223e5d5bfc6c87bdbff2dc14d3356 [file] [log] [blame]
/*
* 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 {
// Always compose in 4x4 for now.
class Concat final : public Transform {
public:
Concat(sk_sp<Transform> a, sk_sp<Transform> 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::AsMatrix44(fA),
TransformPriv::AsMatrix44(fB));
return SkRect::MakeEmpty();
}
SkMatrix asMatrix() const override {
return fComposed;
}
SkMatrix44 asMatrix44() const override {
return fComposed;
}
private:
const sk_sp<Transform> fA, fB;
SkMatrix44 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> Transform::MakeConcat(sk_sp<Transform> a, sk_sp<Transform> b) {
if (!a) {
return b;
}
return b ? sk_make_sp<Concat>(std::move(a), std::move(b))
: a;
}
sk_sp<Matrix> Matrix::Make(const SkMatrix& m) {
return sk_sp<Matrix>(new Matrix(m));
}
Matrix::Matrix(const SkMatrix& m) : fMatrix(m) {}
SkMatrix Matrix::asMatrix() const {
return fMatrix;
}
SkMatrix44 Matrix::asMatrix44() const {
return fMatrix;
}
SkRect Matrix::onRevalidate(InvalidationController*, const SkMatrix&) {
return SkRect::MakeEmpty();
}
sk_sp<Matrix44> Matrix44::Make(const SkMatrix44& m) {
return sk_sp<Matrix44>(new Matrix44(m));
}
Matrix44::Matrix44(const SkMatrix44& m) : fMatrix(m) {}
SkMatrix Matrix44::asMatrix() const {
return fMatrix;
}
SkMatrix44 Matrix44::asMatrix44() const {
return fMatrix;
}
SkRect Matrix44::onRevalidate(InvalidationController*, const SkMatrix&) {
return SkRect::MakeEmpty();
}
TransformEffect::TransformEffect(sk_sp<RenderNode> child, sk_sp<Transform> 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::AsMatrix(fTransform);
SkAutoCanvasRestore acr(canvas, !m.isIdentity());
canvas->concat(m);
this->INHERITED::onRender(canvas, ctx);
}
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::AsMatrix(fTransform);
auto bounds = this->INHERITED::onRevalidate(ic, SkMatrix::Concat(ctm, m));
m.mapRect(&bounds);
return bounds;
}
} // namespace sksg