1 /*
2  * Copyright 2016 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 SKSL_SWIZZLE
9 #define SKSL_SWIZZLE
10 
11 #include "SkSLContext.h"
12 #include "SkSLExpression.h"
13 #include "SkSLUtil.h"
14 
15 namespace SkSL {
16 
17 /**
18  * Given a type and a swizzle component count, returns the type that will result from swizzling. For
19  * instance, swizzling a vec3 with two components will result in a vec2. It is possible to swizzle
20  * with more components than the source vector, as in 'vec2(1).xxxx'.
21  */
get_type(const Context & context,Expression & value,size_t count)22 static const Type& get_type(const Context& context, Expression& value, size_t count) {
23     const Type& base = value.fType.componentType();
24     if (count == 1) {
25         return base;
26     }
27     if (base == *context.fFloat_Type) {
28         switch (count) {
29             case 2: return *context.fVec2_Type;
30             case 3: return *context.fVec3_Type;
31             case 4: return *context.fVec4_Type;
32         }
33     } else if (base == *context.fDouble_Type) {
34         switch (count) {
35             case 2: return *context.fDVec2_Type;
36             case 3: return *context.fDVec3_Type;
37             case 4: return *context.fDVec4_Type;
38         }
39     } else if (base == *context.fInt_Type) {
40         switch (count) {
41             case 2: return *context.fIVec2_Type;
42             case 3: return *context.fIVec3_Type;
43             case 4: return *context.fIVec4_Type;
44         }
45     } else if (base == *context.fUInt_Type) {
46         switch (count) {
47             case 2: return *context.fUVec2_Type;
48             case 3: return *context.fUVec3_Type;
49             case 4: return *context.fUVec4_Type;
50         }
51     } else if (base == *context.fBool_Type) {
52         switch (count) {
53             case 2: return *context.fBVec2_Type;
54             case 3: return *context.fBVec3_Type;
55             case 4: return *context.fBVec4_Type;
56         }
57     }
58     ABORT("cannot swizzle %s\n", value.description().c_str());
59 }
60 
61 /**
62  * Represents a vector swizzle operation such as 'vec2(1, 2, 3).zyx'.
63  */
64 struct Swizzle : public Expression {
SwizzleSwizzle65     Swizzle(const Context& context, std::unique_ptr<Expression> base, std::vector<int> components)
66     : INHERITED(base->fPosition, kSwizzle_Kind, get_type(context, *base, components.size()))
67     , fBase(std::move(base))
68     , fComponents(std::move(components)) {
69         ASSERT(fComponents.size() >= 1 && fComponents.size() <= 4);
70     }
71 
descriptionSwizzle72     SkString description() const override {
73         SkString result = fBase->description() + ".";
74         for (int x : fComponents) {
75             result += "xyzw"[x];
76         }
77         return result;
78     }
79 
80     std::unique_ptr<Expression> fBase;
81     const std::vector<int> fComponents;
82 
83     typedef Expression INHERITED;
84 };
85 
86 } // namespace
87 
88 #endif
89