[sksg] 4x4 matrix support
Refactor the scene graph transform hierarchy to support 4x4 matrices: * rename current Transform to TransformEffect (operates as a render tree effect) * introduce a new Transform abstract base class, to replace current Matrix * refactor existing Matrix as a Transform specialization * introduce a new Matrix44 Transform specialization * refactor the existing composition helper (ComposedMatrix) as Concat, a Transform specialization (using composition instead of Matrix inheritance) Change-Id: Ic3c1b499e10a0a229a7a76d4bef3dbc6a8b49194 Reviewed-on: https://skia-review.googlesource.com/c/182666 Reviewed-by: Mike Reed <reed@google.com> Commit-Queue: Florin Malita <fmalita@chromium.org>
This commit is contained in:
parent
d2fa7e3379
commit
919e209d1a
@ -61,13 +61,13 @@ void AnimationBuilder::log(Logger::Level lvl, const skjson::Value* json,
|
||||
fLogger->log(lvl, buff, jsonstr.c_str());
|
||||
}
|
||||
|
||||
sk_sp<sksg::Matrix> AnimationBuilder::attachMatrix2D(const skjson::ObjectValue& t,
|
||||
AnimatorScope* ascope,
|
||||
sk_sp<sksg::Matrix> parentMatrix) const {
|
||||
sk_sp<sksg::Transform> AnimationBuilder::attachMatrix2D(const skjson::ObjectValue& t,
|
||||
AnimatorScope* ascope,
|
||||
sk_sp<sksg::Transform> parent) const {
|
||||
static const VectorValue g_default_vec_0 = { 0, 0},
|
||||
g_default_vec_100 = {100, 100};
|
||||
|
||||
auto matrix = sksg::Matrix::Make(SkMatrix::I(), parentMatrix);
|
||||
auto matrix = sksg::Matrix::Make(SkMatrix::I());
|
||||
auto adapter = sk_make_sp<TransformAdapter2D>(matrix);
|
||||
|
||||
auto bound = this->bindProperty<VectorValue>(t["a"], ascope,
|
||||
@ -104,16 +104,18 @@ sk_sp<sksg::Matrix> AnimationBuilder::attachMatrix2D(const skjson::ObjectValue&
|
||||
|
||||
const auto dispatched = this->dispatchTransformProperty(adapter);
|
||||
|
||||
return (bound || dispatched) ? matrix : parentMatrix;
|
||||
return (bound || dispatched)
|
||||
? sksg::Transform::MakeConcat(std::move(parent), std::move(matrix))
|
||||
: parent;
|
||||
}
|
||||
|
||||
sk_sp<sksg::Matrix> AnimationBuilder::attachMatrix3D(const skjson::ObjectValue& t,
|
||||
AnimatorScope* ascope,
|
||||
sk_sp<sksg::Matrix> parentMatrix) const {
|
||||
sk_sp<sksg::Transform> AnimationBuilder::attachMatrix3D(const skjson::ObjectValue& t,
|
||||
AnimatorScope* ascope,
|
||||
sk_sp<sksg::Transform> parent) const {
|
||||
static const VectorValue g_default_vec_0 = { 0, 0, 0},
|
||||
g_default_vec_100 = {100, 100, 100};
|
||||
|
||||
auto matrix = sksg::Matrix::Make(SkMatrix::I(), parentMatrix);
|
||||
auto matrix = sksg::Matrix44::Make(SkMatrix::I());
|
||||
auto adapter = sk_make_sp<TransformAdapter3D>(matrix);
|
||||
|
||||
auto bound = this->bindProperty<VectorValue>(t["a"], ascope,
|
||||
@ -156,7 +158,9 @@ sk_sp<sksg::Matrix> AnimationBuilder::attachMatrix3D(const skjson::ObjectValue&
|
||||
|
||||
// TODO: dispatch 3D transform properties
|
||||
|
||||
return bound ? matrix : parentMatrix;
|
||||
return (bound)
|
||||
? sksg::Transform::MakeConcat(std::move(parent), std::move(matrix))
|
||||
: parent;
|
||||
}
|
||||
|
||||
sk_sp<sksg::RenderNode> AnimationBuilder::attachOpacity(const skjson::ObjectValue& jtransform,
|
||||
|
@ -73,12 +73,12 @@ TransformAdapter3D::Vec3::Vec3(const VectorValue& v) {
|
||||
fZ = v.size() > 2 ? v[2] : 0;
|
||||
}
|
||||
|
||||
TransformAdapter3D::TransformAdapter3D(sk_sp<sksg::Matrix> matrix)
|
||||
TransformAdapter3D::TransformAdapter3D(sk_sp<sksg::Matrix44> matrix)
|
||||
: fMatrixNode(std::move(matrix)) {}
|
||||
|
||||
TransformAdapter3D::~TransformAdapter3D() = default;
|
||||
|
||||
SkMatrix TransformAdapter3D::totalMatrix() const {
|
||||
SkMatrix44 TransformAdapter3D::totalMatrix() const {
|
||||
SkMatrix44 t;
|
||||
|
||||
t.setTranslate(-fAnchorPoint.fX, -fAnchorPoint.fY, -fAnchorPoint.fZ);
|
||||
|
@ -21,6 +21,7 @@ class Gradient;
|
||||
class Group;
|
||||
class LinearGradient;
|
||||
class Matrix;
|
||||
class Matrix44;
|
||||
class Path;
|
||||
class RadialGradient;
|
||||
class RRect;
|
||||
@ -105,7 +106,7 @@ private:
|
||||
|
||||
class TransformAdapter3D final : public SkNVRefCnt<TransformAdapter3D> {
|
||||
public:
|
||||
explicit TransformAdapter3D(sk_sp<sksg::Matrix>);
|
||||
explicit TransformAdapter3D(sk_sp<sksg::Matrix44>);
|
||||
~TransformAdapter3D();
|
||||
|
||||
struct Vec3 {
|
||||
@ -124,12 +125,12 @@ public:
|
||||
ADAPTER_PROPERTY(Rotation , Vec3, Vec3({ 0, 0, 0}))
|
||||
ADAPTER_PROPERTY(Scale , Vec3, Vec3({100, 100, 100}))
|
||||
|
||||
SkMatrix totalMatrix() const;
|
||||
SkMatrix44 totalMatrix() const;
|
||||
|
||||
private:
|
||||
void apply();
|
||||
|
||||
sk_sp<sksg::Matrix> fMatrixNode;
|
||||
sk_sp<sksg::Matrix44> fMatrixNode;
|
||||
};
|
||||
|
||||
class GradientAdapter : public SkRefCnt {
|
||||
|
@ -372,7 +372,7 @@ sk_sp<sksg::RenderNode> AnimationBuilder::attachImageAsset(const skjson::ObjectV
|
||||
return std::move(image_node);
|
||||
}
|
||||
|
||||
return sksg::Transform::Make(std::move(image_node),
|
||||
return sksg::TransformEffect::Make(std::move(image_node),
|
||||
SkMatrix::MakeRectToRect(SkRect::Make(image->bounds()),
|
||||
SkRect::Make(asset_size),
|
||||
SkMatrix::kCenter_ScaleToFit));
|
||||
@ -399,13 +399,13 @@ struct AnimationBuilder::AttachLayerContext {
|
||||
AttachLayerContext(const skjson::ArrayValue& jlayers, AnimatorScope* scope)
|
||||
: fLayerList(jlayers), fScope(scope) {}
|
||||
|
||||
const skjson::ArrayValue& fLayerList;
|
||||
AnimatorScope* fScope;
|
||||
SkTHashMap<int, sk_sp<sksg::Matrix>> fLayerMatrixMap;
|
||||
sk_sp<sksg::RenderNode> fCurrentMatte;
|
||||
const skjson::ArrayValue& fLayerList;
|
||||
AnimatorScope* fScope;
|
||||
SkTHashMap<int, sk_sp<sksg::Transform>> fLayerMatrixMap;
|
||||
sk_sp<sksg::RenderNode> fCurrentMatte;
|
||||
|
||||
sk_sp<sksg::Matrix> AttachLayerMatrix(const skjson::ObjectValue& jlayer,
|
||||
const AnimationBuilder* abuilder) {
|
||||
sk_sp<sksg::Transform> attachLayerTransform(const skjson::ObjectValue& jlayer,
|
||||
const AnimationBuilder* abuilder) {
|
||||
const auto layer_index = ParseDefault<int>(jlayer["ind"], -1);
|
||||
if (layer_index < 0)
|
||||
return nullptr;
|
||||
@ -413,13 +413,13 @@ struct AnimationBuilder::AttachLayerContext {
|
||||
if (auto* m = fLayerMatrixMap.find(layer_index))
|
||||
return *m;
|
||||
|
||||
return this->AttachLayerMatrixImpl(jlayer, abuilder, layer_index);
|
||||
return this->attachLayerTransformImpl(jlayer, abuilder, layer_index);
|
||||
}
|
||||
|
||||
private:
|
||||
sk_sp<sksg::Matrix> AttachParentLayerMatrix(const skjson::ObjectValue& jlayer,
|
||||
const AnimationBuilder* abuilder,
|
||||
int layer_index) {
|
||||
sk_sp<sksg::Transform> attachParentLayerTransform(const skjson::ObjectValue& jlayer,
|
||||
const AnimationBuilder* abuilder,
|
||||
int layer_index) {
|
||||
const auto parent_index = ParseDefault<int>(jlayer["parent"], -1);
|
||||
if (parent_index < 0 || parent_index == layer_index)
|
||||
return nullptr;
|
||||
@ -431,29 +431,29 @@ private:
|
||||
if (!l) continue;
|
||||
|
||||
if (ParseDefault<int>((*l)["ind"], -1) == parent_index) {
|
||||
return this->AttachLayerMatrixImpl(*l, abuilder, parent_index);
|
||||
return this->attachLayerTransformImpl(*l, abuilder, parent_index);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
sk_sp<sksg::Matrix> AttachLayerMatrixImpl(const skjson::ObjectValue& jlayer,
|
||||
const AnimationBuilder* abuilder,
|
||||
int layer_index) {
|
||||
sk_sp<sksg::Transform> attachLayerTransformImpl(const skjson::ObjectValue& jlayer,
|
||||
const AnimationBuilder* abuilder,
|
||||
int layer_index) {
|
||||
SkASSERT(!fLayerMatrixMap.find(layer_index));
|
||||
|
||||
// Add a stub entry to break recursion cycles.
|
||||
fLayerMatrixMap.set(layer_index, nullptr);
|
||||
|
||||
auto parent_matrix = this->AttachParentLayerMatrix(jlayer, abuilder, layer_index);
|
||||
auto parent_matrix = this->attachParentLayerTransform(jlayer, abuilder, layer_index);
|
||||
|
||||
if (const skjson::ObjectValue* jtransform = jlayer["ks"]) {
|
||||
auto matrix_node = (ParseDefault<int>(jlayer["ddd"], 0) == 0)
|
||||
auto transform_node = (ParseDefault<int>(jlayer["ddd"], 0) == 0)
|
||||
? abuilder->attachMatrix2D(*jtransform, fScope, std::move(parent_matrix))
|
||||
: abuilder->attachMatrix3D(*jtransform, fScope, std::move(parent_matrix));
|
||||
|
||||
return *fLayerMatrixMap.set(layer_index, std::move(matrix_node));
|
||||
return *fLayerMatrixMap.set(layer_index, std::move(transform_node));
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@ -509,8 +509,8 @@ sk_sp<sksg::RenderNode> AnimationBuilder::attachLayer(const skjson::ObjectValue*
|
||||
layer = AttachMask((*jlayer)["masksProperties"], this, &layer_animators, std::move(layer));
|
||||
|
||||
// Optional layer transform.
|
||||
if (auto layerMatrix = layerCtx->AttachLayerMatrix(*jlayer, this)) {
|
||||
layer = sksg::Transform::Make(std::move(layer), std::move(layerMatrix));
|
||||
if (auto layer_transform = layerCtx->attachLayerTransform(*jlayer, this)) {
|
||||
layer = sksg::TransformEffect::Make(std::move(layer), std::move(layer_transform));
|
||||
}
|
||||
|
||||
// Optional layer opacity.
|
||||
|
@ -33,6 +33,7 @@ class Color;
|
||||
class Matrix;
|
||||
class Path;
|
||||
class RenderNode;
|
||||
class Transform;
|
||||
} // namespace sksg
|
||||
|
||||
namespace skottie {
|
||||
@ -71,10 +72,10 @@ public:
|
||||
|
||||
sk_sp<sksg::Color> attachColor(const skjson::ObjectValue&, AnimatorScope*,
|
||||
const char prop_name[]) const;
|
||||
sk_sp<sksg::Matrix> attachMatrix2D(const skjson::ObjectValue&, AnimatorScope*,
|
||||
sk_sp<sksg::Matrix>) const;
|
||||
sk_sp<sksg::Matrix> attachMatrix3D(const skjson::ObjectValue&, AnimatorScope*,
|
||||
sk_sp<sksg::Matrix>) const;
|
||||
sk_sp<sksg::Transform> attachMatrix2D(const skjson::ObjectValue&, AnimatorScope*,
|
||||
sk_sp<sksg::Transform>) const;
|
||||
sk_sp<sksg::Transform> attachMatrix3D(const skjson::ObjectValue&, AnimatorScope*,
|
||||
sk_sp<sksg::Transform>) const;
|
||||
sk_sp<sksg::RenderNode> attachOpacity(const skjson::ObjectValue&, AnimatorScope*,
|
||||
sk_sp<sksg::RenderNode>) const;
|
||||
sk_sp<sksg::Path> attachPath(const skjson::Value&, AnimatorScope*) const;
|
||||
|
@ -587,7 +587,7 @@ sk_sp<sksg::RenderNode> AnimationBuilder::attachShape(const skjson::ArrayValue*
|
||||
shape_wrapper = sksg::Group::Make(std::move(draws));
|
||||
}
|
||||
|
||||
sk_sp<sksg::Matrix> shape_matrix;
|
||||
sk_sp<sksg::Transform> shape_transform;
|
||||
if (jtransform) {
|
||||
const AutoPropertyTracker apt(this, *jtransform);
|
||||
|
||||
@ -596,8 +596,8 @@ sk_sp<sksg::RenderNode> AnimationBuilder::attachShape(const skjson::ArrayValue*
|
||||
// of the dangling/uncommitted ones.
|
||||
AnimatorScope local_scope;
|
||||
|
||||
if ((shape_matrix = this->attachMatrix2D(*jtransform, &local_scope, nullptr))) {
|
||||
shape_wrapper = sksg::Transform::Make(std::move(shape_wrapper), shape_matrix);
|
||||
if ((shape_transform = this->attachMatrix2D(*jtransform, &local_scope, nullptr))) {
|
||||
shape_wrapper = sksg::TransformEffect::Make(std::move(shape_wrapper), shape_transform);
|
||||
}
|
||||
shape_wrapper = this->attachOpacity(*jtransform, &local_scope, std::move(shape_wrapper));
|
||||
|
||||
@ -609,8 +609,8 @@ sk_sp<sksg::RenderNode> AnimationBuilder::attachShape(const skjson::ArrayValue*
|
||||
|
||||
// Push transformed local geometries to parent list, for subsequent paints.
|
||||
for (auto& geo : geos) {
|
||||
ctx->fGeometryStack->push_back(shape_matrix
|
||||
? sksg::GeometryTransform::Make(std::move(geo), shape_matrix)
|
||||
ctx->fGeometryStack->push_back(shape_transform
|
||||
? sksg::GeometryTransform::Make(std::move(geo), shape_transform)
|
||||
: std::move(geo));
|
||||
}
|
||||
|
||||
|
@ -13,8 +13,6 @@
|
||||
#include "SkPath.h"
|
||||
#include "SkSGTransform.h"
|
||||
|
||||
class SkMatrix;
|
||||
|
||||
namespace sksg {
|
||||
|
||||
/**
|
||||
@ -22,9 +20,10 @@ namespace sksg {
|
||||
*/
|
||||
class GeometryTransform final : public GeometryNode {
|
||||
public:
|
||||
static sk_sp<GeometryTransform> Make(sk_sp<GeometryNode> child, sk_sp<Matrix> matrix) {
|
||||
return child && matrix
|
||||
? sk_sp<GeometryTransform>(new GeometryTransform(std::move(child), std::move(matrix)))
|
||||
static sk_sp<GeometryTransform> Make(sk_sp<GeometryNode> child, sk_sp<Transform> transform) {
|
||||
return child && transform
|
||||
? sk_sp<GeometryTransform>(new GeometryTransform(std::move(child),
|
||||
std::move(transform)))
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
@ -34,7 +33,7 @@ public:
|
||||
|
||||
~GeometryTransform() override;
|
||||
|
||||
const sk_sp<Matrix>& getMatrix() const { return fMatrix; }
|
||||
const sk_sp<Transform>& getTransform() const { return fTransform; }
|
||||
|
||||
protected:
|
||||
void onClip(SkCanvas*, bool antiAlias) const override;
|
||||
@ -44,11 +43,11 @@ protected:
|
||||
SkPath onAsPath() const override;
|
||||
|
||||
private:
|
||||
GeometryTransform(sk_sp<GeometryNode>, sk_sp<Matrix>);
|
||||
GeometryTransform(sk_sp<GeometryNode>, sk_sp<Transform>);
|
||||
|
||||
const sk_sp<GeometryNode> fChild;
|
||||
const sk_sp<Matrix> fMatrix;
|
||||
SkPath fTransformed;
|
||||
const sk_sp<Transform> fTransform;
|
||||
SkPath fTransformedPath;
|
||||
|
||||
using INHERITED = GeometryNode;
|
||||
};
|
||||
|
@ -11,21 +11,40 @@
|
||||
#include "SkSGEffectNode.h"
|
||||
|
||||
#include "SkMatrix.h"
|
||||
#include "SkMatrix44.h"
|
||||
|
||||
namespace sksg {
|
||||
|
||||
/**
|
||||
* Concrete node, wrapping an SkMatrix, with an optional parent Matrix (to allow chaining):
|
||||
*
|
||||
* M' = parent x M
|
||||
* Transformations base class.
|
||||
*/
|
||||
class Matrix : public Node {
|
||||
class Transform : public Node {
|
||||
public:
|
||||
static sk_sp<Matrix> Make(const SkMatrix& m, sk_sp<Matrix> parent = nullptr);
|
||||
// Compose T = A x B
|
||||
static sk_sp<Transform> MakeConcat(sk_sp<Transform> a, sk_sp<Transform> b);
|
||||
|
||||
// TODO: hide these from public API?
|
||||
virtual SkMatrix asMatrix () const = 0;
|
||||
virtual SkMatrix44 asMatrix44() const = 0;
|
||||
|
||||
protected:
|
||||
Transform();
|
||||
|
||||
private:
|
||||
using INHERITED = Node;
|
||||
};
|
||||
|
||||
/**
|
||||
* Concrete, SkMatrix-backed transformation.
|
||||
*/
|
||||
class Matrix final : public Transform {
|
||||
public:
|
||||
static sk_sp<Matrix> Make(const SkMatrix& m);
|
||||
|
||||
SG_ATTRIBUTE(Matrix, SkMatrix, fMatrix)
|
||||
|
||||
virtual const SkMatrix& getTotalMatrix() const;
|
||||
SkMatrix asMatrix () const override;
|
||||
SkMatrix44 asMatrix44() const override;
|
||||
|
||||
protected:
|
||||
explicit Matrix(const SkMatrix&);
|
||||
@ -35,27 +54,50 @@ protected:
|
||||
private:
|
||||
SkMatrix fMatrix;
|
||||
|
||||
typedef Node INHERITED;
|
||||
using INHERITED = Transform;
|
||||
};
|
||||
|
||||
/**
|
||||
* Concrete Effect node, binding a Matrix to a RenderNode.
|
||||
* Concrete, SkMatrix44-backed transformation.
|
||||
*/
|
||||
class Transform final : public EffectNode {
|
||||
class Matrix44 final : public Transform {
|
||||
public:
|
||||
static sk_sp<Transform> Make(sk_sp<RenderNode> child, sk_sp<Matrix> matrix) {
|
||||
return child && matrix
|
||||
? sk_sp<Transform>(new Transform(std::move(child), std::move(matrix)))
|
||||
static sk_sp<Matrix44> Make(const SkMatrix44& m);
|
||||
|
||||
SG_ATTRIBUTE(Matrix, SkMatrix44, fMatrix)
|
||||
|
||||
SkMatrix asMatrix () const override;
|
||||
SkMatrix44 asMatrix44() const override;
|
||||
|
||||
protected:
|
||||
explicit Matrix44(const SkMatrix44&);
|
||||
|
||||
SkRect onRevalidate(InvalidationController*, const SkMatrix&) override;
|
||||
|
||||
private:
|
||||
SkMatrix44 fMatrix;
|
||||
|
||||
using INHERITED = Transform;
|
||||
};
|
||||
|
||||
/**
|
||||
* Concrete Effect node, binding a Transform to a RenderNode.
|
||||
*/
|
||||
class TransformEffect final : public EffectNode {
|
||||
public:
|
||||
static sk_sp<TransformEffect> Make(sk_sp<RenderNode> child, sk_sp<Transform> transform) {
|
||||
return child && transform
|
||||
? sk_sp<TransformEffect>(new TransformEffect(std::move(child), std::move(transform)))
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
static sk_sp<Transform> Make(sk_sp<RenderNode> child, const SkMatrix& m) {
|
||||
static sk_sp<TransformEffect> Make(sk_sp<RenderNode> child, const SkMatrix& m) {
|
||||
return Make(std::move(child), Matrix::Make(m));
|
||||
}
|
||||
|
||||
~Transform() override;
|
||||
~TransformEffect() override;
|
||||
|
||||
const sk_sp<Matrix>& getMatrix() const { return fMatrix; }
|
||||
const sk_sp<Transform>& getTransform() const { return fTransform; }
|
||||
|
||||
protected:
|
||||
void onRender(SkCanvas*, const RenderContext*) const override;
|
||||
@ -63,9 +105,9 @@ protected:
|
||||
SkRect onRevalidate(InvalidationController*, const SkMatrix&) override;
|
||||
|
||||
private:
|
||||
Transform(sk_sp<RenderNode>, sk_sp<Matrix>);
|
||||
TransformEffect(sk_sp<RenderNode>, sk_sp<Transform>);
|
||||
|
||||
const sk_sp<Matrix> fMatrix;
|
||||
const sk_sp<Transform> fTransform;
|
||||
|
||||
typedef EffectNode INHERITED;
|
||||
};
|
||||
|
@ -144,7 +144,7 @@ protected:
|
||||
SkMatrix::MakeRectToRect(SkRect::MakeWH(1, 1),
|
||||
SkRect::MakeIWH(this->width(), this->height()),
|
||||
SkMatrix::kFill_ScaleToFit));
|
||||
auto root = sksg::Transform::Make(std::move(group), fContentMatrix);
|
||||
auto root = sksg::TransformEffect::Make(std::move(group), fContentMatrix);
|
||||
fScene = sksg::Scene::Make(std::move(root), sksg::AnimatorList());
|
||||
|
||||
// Off we go.
|
||||
|
@ -11,44 +11,44 @@
|
||||
|
||||
namespace sksg {
|
||||
|
||||
GeometryTransform::GeometryTransform(sk_sp<GeometryNode> child, sk_sp<Matrix> matrix)
|
||||
GeometryTransform::GeometryTransform(sk_sp<GeometryNode> child, sk_sp<Transform> transform)
|
||||
: fChild(std::move(child))
|
||||
, fMatrix(std::move(matrix)) {
|
||||
, fTransform(std::move(transform)) {
|
||||
this->observeInval(fChild);
|
||||
this->observeInval(fMatrix);
|
||||
this->observeInval(fTransform);
|
||||
}
|
||||
|
||||
GeometryTransform::~GeometryTransform() {
|
||||
this->unobserveInval(fChild);
|
||||
this->unobserveInval(fMatrix);
|
||||
this->unobserveInval(fTransform);
|
||||
}
|
||||
|
||||
void GeometryTransform::onClip(SkCanvas* canvas, bool antiAlias) const {
|
||||
canvas->clipPath(fTransformed, SkClipOp::kIntersect, antiAlias);
|
||||
canvas->clipPath(fTransformedPath, SkClipOp::kIntersect, antiAlias);
|
||||
}
|
||||
|
||||
void GeometryTransform::onDraw(SkCanvas* canvas, const SkPaint& paint) const {
|
||||
canvas->drawPath(fTransformed, paint);
|
||||
canvas->drawPath(fTransformedPath, paint);
|
||||
}
|
||||
|
||||
SkRect GeometryTransform::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) {
|
||||
SkASSERT(this->hasInval());
|
||||
|
||||
// We don't care about matrix reval results.
|
||||
fMatrix->revalidate(ic, ctm);
|
||||
const auto& m = fMatrix->getMatrix();
|
||||
fTransform->revalidate(ic, ctm);
|
||||
const auto m = fTransform->asMatrix();
|
||||
|
||||
auto bounds = fChild->revalidate(ic, ctm);
|
||||
fTransformed = fChild->asPath();
|
||||
fTransformed.transform(m);
|
||||
fTransformed.shrinkToFit();
|
||||
fTransformedPath = fChild->asPath();
|
||||
fTransformedPath.transform(m);
|
||||
fTransformedPath.shrinkToFit();
|
||||
|
||||
m.mapRect(&bounds);
|
||||
return bounds;
|
||||
}
|
||||
|
||||
SkPath GeometryTransform::onAsPath() const {
|
||||
return fTransformed;
|
||||
return fTransformedPath;
|
||||
}
|
||||
|
||||
} // namespace sksg
|
||||
|
@ -10,53 +10,75 @@
|
||||
#include "SkCanvas.h"
|
||||
|
||||
namespace sksg {
|
||||
|
||||
namespace {
|
||||
|
||||
class ComposedMatrix final : public Matrix {
|
||||
// Always compose in 4x4 for now.
|
||||
class Concat final : public Transform {
|
||||
public:
|
||||
ComposedMatrix(const SkMatrix& m, sk_sp<Matrix> parent)
|
||||
: INHERITED(m)
|
||||
, fParent(std::move(parent)) {
|
||||
SkASSERT(fParent);
|
||||
this->observeInval(fParent);
|
||||
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);
|
||||
}
|
||||
|
||||
~ComposedMatrix() override {
|
||||
this->unobserveInval(fParent);
|
||||
~Concat() override {
|
||||
this->unobserveInval(fA);
|
||||
this->unobserveInval(fB);
|
||||
}
|
||||
|
||||
const SkMatrix& getTotalMatrix() const override {
|
||||
SkASSERT(!this->hasInval());
|
||||
return fTotalMatrix;
|
||||
SkMatrix asMatrix() const override {
|
||||
return fComposed;
|
||||
}
|
||||
|
||||
SkMatrix44 asMatrix44() const override {
|
||||
return fComposed;
|
||||
}
|
||||
|
||||
protected:
|
||||
SkRect onRevalidate(InvalidationController* ic, const SkMatrix& ctm) override {
|
||||
fParent->revalidate(ic, ctm);
|
||||
fTotalMatrix = SkMatrix::Concat(fParent->getTotalMatrix(), this->getMatrix());
|
||||
fA->revalidate(ic, ctm);
|
||||
fB->revalidate(ic, ctm);
|
||||
|
||||
fComposed.setConcat(fA->asMatrix44(), fB->asMatrix44());
|
||||
return SkRect::MakeEmpty();
|
||||
}
|
||||
|
||||
private:
|
||||
const sk_sp<Matrix> fParent;
|
||||
SkMatrix fTotalMatrix; // cached during revalidation.
|
||||
const sk_sp<Transform> fA, fB;
|
||||
SkMatrix44 fComposed;
|
||||
|
||||
using INHERITED = Matrix;
|
||||
using INHERITED = Transform;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
sk_sp<Matrix> Matrix::Make(const SkMatrix& m, sk_sp<Matrix> parent) {
|
||||
return sk_sp<Matrix>(parent ? new ComposedMatrix(m, std::move(parent))
|
||||
: new Matrix(m));
|
||||
// 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;
|
||||
}
|
||||
|
||||
// Matrix nodes don't generate damage on their own, but via aggregation ancestor Transform nodes.
|
||||
Matrix::Matrix(const SkMatrix& m)
|
||||
: INHERITED(kBubbleDamage_Trait)
|
||||
, fMatrix(m) {}
|
||||
sk_sp<Matrix> Matrix::Make(const SkMatrix& m) {
|
||||
return sk_sp<Matrix>(new Matrix(m));
|
||||
}
|
||||
|
||||
const SkMatrix& Matrix::getTotalMatrix() const {
|
||||
Matrix::Matrix(const SkMatrix& m) : fMatrix(m) {}
|
||||
|
||||
SkMatrix Matrix::asMatrix() const {
|
||||
return fMatrix;
|
||||
}
|
||||
|
||||
SkMatrix44 Matrix::asMatrix44() const {
|
||||
return fMatrix;
|
||||
}
|
||||
|
||||
@ -64,30 +86,48 @@ SkRect Matrix::onRevalidate(InvalidationController*, const SkMatrix&) {
|
||||
return SkRect::MakeEmpty();
|
||||
}
|
||||
|
||||
Transform::Transform(sk_sp<RenderNode> child, sk_sp<Matrix> matrix)
|
||||
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))
|
||||
, fMatrix(std::move(matrix)) {
|
||||
this->observeInval(fMatrix);
|
||||
, fTransform(std::move(transform)) {
|
||||
this->observeInval(fTransform);
|
||||
}
|
||||
|
||||
Transform::~Transform() {
|
||||
this->unobserveInval(fMatrix);
|
||||
TransformEffect::~TransformEffect() {
|
||||
this->unobserveInval(fTransform);
|
||||
}
|
||||
|
||||
void Transform::onRender(SkCanvas* canvas, const RenderContext* ctx) const {
|
||||
const auto& m = fMatrix->getTotalMatrix();
|
||||
void TransformEffect::onRender(SkCanvas* canvas, const RenderContext* ctx) const {
|
||||
const auto m = fTransform->asMatrix();
|
||||
SkAutoCanvasRestore acr(canvas, !m.isIdentity());
|
||||
canvas->concat(m);
|
||||
this->INHERITED::onRender(canvas, ctx);
|
||||
}
|
||||
|
||||
SkRect Transform::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) {
|
||||
SkRect TransformEffect::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) {
|
||||
SkASSERT(this->hasInval());
|
||||
|
||||
// We don't care about matrix reval results.
|
||||
fMatrix->revalidate(ic, ctm);
|
||||
fTransform->revalidate(ic, ctm);
|
||||
|
||||
const auto& m = fMatrix->getTotalMatrix();
|
||||
const auto m = fTransform->asMatrix();
|
||||
auto bounds = this->INHERITED::onRevalidate(ic, SkMatrix::Concat(ctm, m));
|
||||
m.mapRect(&bounds);
|
||||
|
||||
|
@ -61,7 +61,7 @@ static void inval_test1(skiatest::Reporter* reporter) {
|
||||
r2 = sksg::Rect::Make(SkRect::MakeWH(100, 100));
|
||||
auto grp = sksg::Group::Make();
|
||||
auto matrix = sksg::Matrix::Make(SkMatrix::I());
|
||||
auto root = sksg::Transform::Make(grp, matrix);
|
||||
auto root = sksg::TransformEffect::Make(grp, matrix);
|
||||
|
||||
grp->addChild(sksg::Draw::Make(r1, color));
|
||||
grp->addChild(sksg::Draw::Make(r2, color));
|
||||
@ -129,9 +129,10 @@ static void inval_test2(skiatest::Reporter* reporter) {
|
||||
auto color = sksg::Color::Make(0xff000000);
|
||||
auto rect = sksg::Rect::Make(SkRect::MakeWH(100, 100));
|
||||
auto m1 = sksg::Matrix::Make(SkMatrix::I()),
|
||||
m2 = sksg::Matrix::Make(SkMatrix::I(), m1);
|
||||
auto t1 = sksg::Transform::Make(sksg::Draw::Make(rect, color), m2),
|
||||
t2 = sksg::Transform::Make(sksg::Draw::Make(rect, color), m1);
|
||||
m2 = sksg::Matrix::Make(SkMatrix::I());
|
||||
auto t1 = sksg::TransformEffect::Make(sksg::Draw::Make(rect, color),
|
||||
sksg::Transform::MakeConcat(m1, m2)),
|
||||
t2 = sksg::TransformEffect::Make(sksg::Draw::Make(rect, color), m1);
|
||||
auto root = sksg::Group::Make();
|
||||
root->addChild(t1);
|
||||
root->addChild(t2);
|
||||
|
@ -998,7 +998,7 @@ SkMatrix44& SkMatrix44::operator=(const SkMatrix& src) {
|
||||
SkMatrix44::operator SkMatrix() const {
|
||||
SkMatrix dst;
|
||||
|
||||
dst[SkMatrix::kMScaleX] = SkMScalarToScalar(fMat[0][0]);
|
||||
dst[SkMatrix::kMScaleX] = SkMScalarToScalar(fMat[0][0]);
|
||||
dst[SkMatrix::kMSkewX] = SkMScalarToScalar(fMat[1][0]);
|
||||
dst[SkMatrix::kMTransX] = SkMScalarToScalar(fMat[3][0]);
|
||||
|
||||
|
@ -101,9 +101,10 @@ SkMatrix SlideMatrix(const sk_sp<Slide>& slide, const SkRect& dst) {
|
||||
} // namespace
|
||||
|
||||
struct SlideDir::Rec {
|
||||
sk_sp<Slide> fSlide;
|
||||
sk_sp<sksg::Transform> fTransform;
|
||||
SkRect fRect;
|
||||
sk_sp<Slide> fSlide;
|
||||
sk_sp<sksg::RenderNode> fSlideRoot;
|
||||
sk_sp<sksg::Matrix> fMatrix;
|
||||
SkRect fRect;
|
||||
};
|
||||
|
||||
class SlideDir::FocusController final : public sksg::Animator {
|
||||
@ -128,9 +129,9 @@ public:
|
||||
fTarget = target;
|
||||
|
||||
// Move the shade & slide to front.
|
||||
fDir->fRoot->removeChild(fTarget->fTransform);
|
||||
fDir->fRoot->removeChild(fTarget->fSlideRoot);
|
||||
fDir->fRoot->addChild(fShade);
|
||||
fDir->fRoot->addChild(fTarget->fTransform);
|
||||
fDir->fRoot->addChild(fTarget->fSlideRoot);
|
||||
|
||||
fM0 = SlideMatrix(fTarget->fSlide, fTarget->fRect);
|
||||
fM1 = SlideMatrix(fTarget->fSlide, fRect);
|
||||
@ -197,7 +198,7 @@ protected:
|
||||
}
|
||||
|
||||
SkASSERT(fTarget);
|
||||
fTarget->fTransform->getMatrix()->setMatrix(m);
|
||||
fTarget->fMatrix->setMatrix(m);
|
||||
|
||||
const auto shadeOpacity = fOpacity0 + map_t * (fOpacity1 - fOpacity0);
|
||||
fShadePaint->setOpacity(shadeOpacity);
|
||||
@ -305,7 +306,7 @@ void SlideDir::load(SkScalar winWidth, SkScalar winHeight) {
|
||||
fCellSize.height()),
|
||||
slideRect = cell.makeInset(kPadding.width(), kPadding.height());
|
||||
|
||||
auto slideMatrix = SlideMatrix(slide, slideRect);
|
||||
auto slideMatrix = sksg::Matrix::Make(SlideMatrix(slide, slideRect));
|
||||
auto adapter = sk_make_sp<SlideAdapter>(slide);
|
||||
auto slideGrp = sksg::Group::Make();
|
||||
slideGrp->addChild(sksg::Draw::Make(sksg::Rect::Make(SkRect::MakeIWH(slideSize.width(),
|
||||
@ -314,13 +315,13 @@ void SlideDir::load(SkScalar winWidth, SkScalar winHeight) {
|
||||
slideGrp->addChild(adapter);
|
||||
slideGrp->addChild(MakeLabel(slide->getName(),
|
||||
SkPoint::Make(slideSize.width() / 2, slideSize.height()),
|
||||
slideMatrix));
|
||||
auto slideTransform = sksg::Transform::Make(std::move(slideGrp), slideMatrix);
|
||||
slideMatrix->getMatrix()));
|
||||
auto slideRoot = sksg::TransformEffect::Make(std::move(slideGrp), slideMatrix);
|
||||
|
||||
sceneAnimators.push_back(adapter->makeForwardingAnimator());
|
||||
|
||||
fRoot->addChild(slideTransform);
|
||||
fRecs.push_back({ slide, slideTransform, slideRect });
|
||||
fRoot->addChild(slideRoot);
|
||||
fRecs.push_back({ slide, slideRoot, slideMatrix, slideRect });
|
||||
}
|
||||
|
||||
fScene = sksg::Scene::Make(fRoot, std::move(sceneAnimators));
|
||||
|
Loading…
Reference in New Issue
Block a user