1 /*
2  * Copyright 2020 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #ifndef GrVectorXform_DEFINED
9 #define GrVectorXform_DEFINED
10 
11 #include "include/core/SkMatrix.h"
12 #include "include/private/SkVx.h"
13 
14 // Represents the upper-left 2x2 matrix of an affine transform for applying to vectors:
15 //
16 //     VectorXform(p1 - p0) == M * float3(p1, 1) - M * float3(p0, 1)
17 //
18 class GrVectorXform {
19 public:
20     using float2 = skvx::Vec<2, float>;
21     using float4 = skvx::Vec<4, float>;
GrVectorXform()22     explicit GrVectorXform() : fType(Type::kIdentity) {}
GrVectorXform(const SkMatrix & m)23     explicit GrVectorXform(const SkMatrix& m) {
24         SkASSERT(!m.hasPerspective());
25         if (m.getType() & SkMatrix::kAffine_Mask) {
26             fType = Type::kAffine;
27             fScaleXSkewY = {m.getScaleX(), m.getSkewY()};
28             fSkewXScaleY = {m.getSkewX(), m.getScaleY()};
29             fScaleXYXY = {m.getScaleX(), m.getScaleY(), m.getScaleX(), m.getScaleY()};
30             fSkewXYXY = {m.getSkewX(), m.getSkewY(), m.getSkewX(), m.getSkewY()};
31         } else if (m.getType() & SkMatrix::kScale_Mask) {
32             fType = Type::kScale;
33             fScaleXY = {m.getScaleX(), m.getScaleY()};
34             fScaleXYXY = {m.getScaleX(), m.getScaleY(), m.getScaleX(), m.getScaleY()};
35         } else {
36             SkASSERT(!(m.getType() & ~SkMatrix::kTranslate_Mask));
37             fType = Type::kIdentity;
38         }
39     }
operator()40     float2 operator()(float2 vector) const {
41         switch (fType) {
42             case Type::kIdentity:
43                 return vector;
44             case Type::kScale:
45                 return fScaleXY * vector;
46             case Type::kAffine:
47                 return fScaleXSkewY * float2(vector[0]) + fSkewXScaleY * vector[1];
48         }
49         SkUNREACHABLE;
50     }
operator()51     float4 operator()(float4 vectors) const {
52         switch (fType) {
53             case Type::kIdentity:
54                 return vectors;
55             case Type::kScale:
56                 return vectors * fScaleXYXY;
57             case Type::kAffine:
58                 return fScaleXYXY * vectors + fSkewXYXY * skvx::shuffle<1,0,3,2>(vectors);
59         }
60         SkUNREACHABLE;
61     }
62 private:
63     enum class Type { kIdentity, kScale, kAffine } fType;
64     union { float2 fScaleXY, fScaleXSkewY; };
65     float2 fSkewXScaleY;
66     float4 fScaleXYXY;
67     float4 fSkewXYXY;
68 };
69 
70 #endif
71