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