blob: 5a47a8b11c4a1d6ea65cb394ae0bd5a07d89d7f0 [file] [log] [blame]
/*
* Copyright 2020 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrVectorXform_DEFINED
#define GrVectorXform_DEFINED
#include "include/core/SkMatrix.h"
#include "include/private/SkVx.h"
// Represents the upper-left 2x2 matrix of an affine transform for applying to vectors:
//
// VectorXform(p1 - p0) == M * float3(p1, 1) - M * float3(p0, 1)
//
class GrVectorXform {
public:
using float2 = skvx::Vec<2, float>;
using float4 = skvx::Vec<4, float>;
explicit GrVectorXform() : fType(Type::kIdentity) {}
explicit GrVectorXform(const SkMatrix& m) {
SkASSERT(!m.hasPerspective());
if (m.getType() & SkMatrix::kAffine_Mask) {
fType = Type::kAffine;
fScaleXSkewY = {m.getScaleX(), m.getSkewY()};
fSkewXScaleY = {m.getSkewX(), m.getScaleY()};
fScaleXYXY = {m.getScaleX(), m.getScaleY(), m.getScaleX(), m.getScaleY()};
fSkewXYXY = {m.getSkewX(), m.getSkewY(), m.getSkewX(), m.getSkewY()};
} else if (m.getType() & SkMatrix::kScale_Mask) {
fType = Type::kScale;
fScaleXY = {m.getScaleX(), m.getScaleY()};
fScaleXYXY = {m.getScaleX(), m.getScaleY(), m.getScaleX(), m.getScaleY()};
} else {
SkASSERT(!(m.getType() & ~SkMatrix::kTranslate_Mask));
fType = Type::kIdentity;
}
}
float2 operator()(float2 vector) const {
switch (fType) {
case Type::kIdentity:
return vector;
case Type::kScale:
return fScaleXY * vector;
case Type::kAffine:
return fScaleXSkewY * float2(vector[0]) + fSkewXScaleY * vector[1];
}
SkUNREACHABLE;
}
float4 operator()(float4 vectors) const {
switch (fType) {
case Type::kIdentity:
return vectors;
case Type::kScale:
return vectors * fScaleXYXY;
case Type::kAffine:
return fScaleXYXY * vectors + fSkewXYXY * skvx::shuffle<1,0,3,2>(vectors);
}
SkUNREACHABLE;
}
private:
enum class Type { kIdentity, kScale, kAffine } fType;
union { float2 fScaleXY, fScaleXSkewY; };
float2 fSkewXScaleY;
float4 fScaleXYXY;
float4 fSkewXYXY;
};
#endif