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/SkNx.h"
13
14// We enclose this class in the anonymous namespace so it can have Sk2f/Sk4f members.
15namespace { // NOLINT(google-build-namespaces)
16
17// Represents the upper-left 2x2 matrix of an affine transform for applying to vectors:
18//
19// VectorXform(p1 - p0) == M * float3(p1, 1) - M * float3(p0, 1)
20//
21class GrVectorXform {
22public:
23 explicit GrVectorXform() : fType(Type::kIdentity) {}
24 explicit GrVectorXform(const SkMatrix& m) {
25 SkASSERT(!m.hasPerspective());
26 if (m.getType() & SkMatrix::kAffine_Mask) {
27 fType = Type::kAffine;
28 fScaleXSkewY = {m.getScaleX(), m.getSkewY()};
29 fSkewXScaleY = {m.getSkewX(), m.getScaleY()};
30 fScaleXYXY = {m.getScaleX(), m.getScaleY(), m.getScaleX(), m.getScaleY()};
31 fSkewXYXY = {m.getSkewX(), m.getSkewY(), m.getSkewX(), m.getSkewY()};
32 } else if (m.getType() & SkMatrix::kScale_Mask) {
33 fType = Type::kScale;
34 fScaleXY = {m.getScaleX(), m.getScaleY()};
35 fScaleXYXY = {m.getScaleX(), m.getScaleY(), m.getScaleX(), m.getScaleY()};
36 } else {
37 SkASSERT(!(m.getType() & ~SkMatrix::kTranslate_Mask));
38 fType = Type::kIdentity;
39 }
40 }
41 Sk2f operator()(const Sk2f& vector) const {
42 switch (fType) {
43 case Type::kIdentity:
44 return vector;
45 case Type::kScale:
46 return fScaleXY * vector;
47 case Type::kAffine:
48 return fScaleXSkewY * vector[0] + fSkewXScaleY * vector[1];
49 }
50 SkUNREACHABLE;
51 }
52 Sk4f operator()(const Sk4f& vectors) const {
53 switch (fType) {
54 case Type::kIdentity:
55 return vectors;
56 case Type::kScale:
57 return vectors * fScaleXYXY;
58 case Type::kAffine:
59 return fScaleXYXY * vectors + fSkewXYXY * SkNx_shuffle<1,0,3,2>(vectors);
60 }
61 SkUNREACHABLE;
62 }
63private:
64 enum class Type { kIdentity, kScale, kAffine } fType;
65 union { Sk2f fScaleXY, fScaleXSkewY; };
66 Sk2f fSkewXScaleY;
67 Sk4f fScaleXYXY;
68 Sk4f fSkewXYXY;
69};
70
71} // namespace
72
73#endif
74