#ifndef GrVectorXform_DEFINED
#define GrVectorXform_DEFINED
#include "include/core/SkMatrix.h"
#include "include/private/SkVx.h"
namespace pk {
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) { *this = m; }
GrVectorXform& operator=(const SkMatrix& m) {
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 {
fType = Type::kIdentity;
}
return *this;
}
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];
}
}
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);
}
}
private:
enum class Type { kIdentity, kScale, kAffine } fType;
union {
float2 fScaleXY, fScaleXSkewY;
};
float2 fSkewXScaleY;
float4 fScaleXYXY;
float4 fSkewXYXY;
};
}
#endif