[graphite] Add more utility and SkM44/SkMatrix interop to Transform class

Change-Id: I028bd133778d14edcb22ccef0c35c5a8e3d7d552
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/554516
Reviewed-by: Jim Van Verth <jvanverth@google.com>
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
This commit is contained in:
Michael Ludwig 2022-06-29 14:43:59 -04:00 committed by SkCQ
parent 987901fa3f
commit 9d82f9e4b8
3 changed files with 74 additions and 0 deletions

View File

@ -30,6 +30,7 @@ struct SK_API SkV2 {
friend SkV2 operator*(SkV2 v, SkScalar s) { return {v.x*s, v.y*s}; }
friend SkV2 operator*(SkScalar s, SkV2 v) { return {v.x*s, v.y*s}; }
friend SkV2 operator/(SkV2 v, SkScalar s) { return {v.x/s, v.y/s}; }
friend SkV2 operator/(SkScalar s, SkV2 v) { return {s/v.x, s/v.y}; }
void operator+=(SkV2 v) { *this = *this + v; }
void operator-=(SkV2 v) { *this = *this - v; }

View File

@ -93,6 +93,15 @@ Transform::Transform(const SkM44& m) : fM(m) {
fType = get_matrix_info(m, &fInvM, &fScale);
}
const Transform& Transform::Identity() {
static const Transform kIdentity{SkM44()};
return kIdentity;
}
const Transform& Transform::Invalid() {
static const Transform kInvalid{SkM44(SkM44::kNaN_Constructor)};
return kInvalid;
}
bool Transform::operator==(const Transform& t) const {
// Checking fM should be sufficient as all other values are computed from it.
SkASSERT(fM != t.fM || (fInvM == t.fInvM && fType == t.fType && fScale == t.fScale));
@ -131,4 +140,50 @@ void Transform::inverseMapPoints(const SkV4* deviceIn, SkV4* localOut, int count
return map_points(fInvM, deviceIn, localOut, count);
}
Transform Transform::preTranslate(float x, float y) const {
Transform t = *this;
t.fM.preTranslate(x, y);
t.fInvM.postTranslate(-x, -y);
// Under normal conditions, type and scale won't change, but if we've overflown the translation
// components, mark the matrix as invalid.
if (!t.fM.isFinite() || !t.fInvM.isFinite()) {
t.fType = Type::kInvalid;
}
return t;
}
Transform Transform::postTranslate(float x, float y) const {
Transform t = *this;
t.fM.postTranslate(x, y);
t.fInvM.preTranslate(-x, -y);
if (!t.fM.isFinite() || !t.fInvM.isFinite()) {
t.fType = Type::kInvalid;
}
return t;
}
Transform Transform::concat(const Transform& t) const {
Transform c = {fM * t.fM, t.fInvM * fInvM, std::max(fType, t.fType), {fScale * t.fScale}};
if (!c.fM.isFinite() || !c.fInvM.isFinite()) {
c.fType = Type::kInvalid;
}
return c;
}
Transform Transform::concatInverse(const Transform& t) const {
Transform c = {fM * t.fInvM, t.fM * fInvM, std::max(fType, t.fType), {fScale * (1.f/t.fScale)}};
if (!c.fM.isFinite() || !c.fInvM.isFinite()) {
c.fType = Type::kInvalid;
}
return c;
}
Transform Transform::concatInverse(const SkM44& t) const {
// saves a multiply compared to inverting just t and then computing fM*t^-1 and t*fInvM, if we
// instead start with (t*fInvM) and swap definition of computed fM and fInvM.
Transform inverse{t * fInvM};
return {inverse.fInvM, inverse.fM, inverse.fType, 1.f / inverse.fScale};
}
} // namespace skgpu::graphite

View File

@ -44,6 +44,9 @@ public:
explicit Transform(const SkM44& m);
Transform(const Transform& t) = default;
static const Transform& Identity();
static const Transform& Invalid();
Transform& operator=(const Transform& t) = default;
operator const SkM44&() const { return fM; }
@ -70,7 +73,22 @@ public:
void mapPoints(const SkV4* localIn, SkV4* deviceOut, int count) const;
void inverseMapPoints(const SkV4* deviceIn, SkV4* localOut, int count) const;
// Returns a transform equal to the pre- or post-translating this matrix
Transform preTranslate(float x, float y) const;
Transform postTranslate(float x, float y) const;
// Returns a transform equal to (this * t)
Transform concat(const Transform& t) const;
Transform concat(const SkM44& t) const { return Transform(fM * t); }
// Returns a transform equal to (this * t^-1)
Transform concatInverse(const Transform& t) const;
Transform concatInverse(const SkM44& t) const;
private:
Transform(const SkM44& m, const SkM44& invM, Type type, const SkV2 scale)
: fM(m), fInvM(invM), fType(type), fScale(scale) {}
SkM44 fM;
SkM44 fInvM; // M^-1
Type fType;