• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 skgpu_Swizzle_DEFINED
9 #define skgpu_Swizzle_DEFINED
10 
11 #include "include/core/SkString.h"
12 #include "include/private/SkColorData.h"
13 
14 class SkRasterPipeline;
15 
16 namespace skgpu {
17 
18 /** Represents a rgba swizzle. It can be converted either into a string or a eight bit int. */
19 class Swizzle {
20 public:
Swizzle()21     constexpr Swizzle() : Swizzle("rgba") {}
22     explicit constexpr Swizzle(const char c[4]);
23 
24     constexpr Swizzle(const Swizzle&);
25     constexpr Swizzle& operator=(const Swizzle& that);
26 
27     static constexpr Swizzle Concat(const Swizzle& a, const Swizzle& b);
28 
29     constexpr bool operator==(const Swizzle& that) const { return fKey == that.fKey; }
30     constexpr bool operator!=(const Swizzle& that) const { return !(*this == that); }
31 
32     /** Compact representation of the swizzle suitable for a key. */
asKey()33     constexpr uint16_t asKey() const { return fKey; }
34 
35     /** 4 char null terminated string consisting only of chars 'r', 'g', 'b', 'a', '0', and '1'. */
36     SkString asString() const;
37 
38     constexpr char operator[](int i) const {
39         SkASSERT(i >= 0 && i < 4);
40         int idx = (fKey >> (4U * i)) & 0xfU;
41         return IToC(idx);
42     }
43 
44     /** Applies this swizzle to the input color and returns the swizzled color. */
45     constexpr std::array<float, 4> applyTo(std::array<float, 4> color) const;
46 
47     /** Convenience version for SkRGBA colors. */
48     template <SkAlphaType AlphaType>
applyTo(SkRGBA4f<AlphaType> color)49     constexpr SkRGBA4f<AlphaType> applyTo(SkRGBA4f<AlphaType> color) const {
50         std::array<float, 4> result = this->applyTo(color.array());
51         return {result[0], result[1], result[2], result[3]};
52     }
53 
54     void apply(SkRasterPipeline*) const;
55 
RGBA()56     static constexpr Swizzle RGBA() { return Swizzle("rgba"); }
BGRA()57     static constexpr Swizzle BGRA() { return Swizzle("bgra"); }
RRRA()58     static constexpr Swizzle RRRA() { return Swizzle("rrra"); }
RGB1()59     static constexpr Swizzle RGB1() { return Swizzle("rgb1"); }
60 
61 private:
Swizzle(uint16_t key)62     explicit constexpr Swizzle(uint16_t key) : fKey(key) {}
63 
64     static constexpr float ComponentIndexToFloat(std::array<float, 4>, int idx);
65     static constexpr int CToI(char c);
66     static constexpr char IToC(int idx);
67 
68     uint16_t fKey;
69 };
70 
Swizzle(const char c[4])71 constexpr Swizzle::Swizzle(const char c[4])
72         : fKey((CToI(c[0]) << 0) | (CToI(c[1]) << 4) | (CToI(c[2]) << 8) | (CToI(c[3]) << 12)) {}
73 
Swizzle(const Swizzle & that)74 constexpr Swizzle::Swizzle(const Swizzle& that)
75         : fKey(that.fKey) {}
76 
77 constexpr Swizzle& Swizzle::operator=(const Swizzle& that) {
78     fKey = that.fKey;
79     return *this;
80 }
81 
applyTo(std::array<float,4> color)82 constexpr std::array<float, 4> Swizzle::applyTo(std::array<float, 4> color) const {
83     uint32_t key = fKey;
84     // Index of the input color that should be mapped to output r.
85     int idx = (key & 15);
86     float outR = ComponentIndexToFloat(color, idx);
87     key >>= 4;
88     idx = (key & 15);
89     float outG = ComponentIndexToFloat(color, idx);
90     key >>= 4;
91     idx = (key & 15);
92     float outB = ComponentIndexToFloat(color, idx);
93     key >>= 4;
94     idx = (key & 15);
95     float outA = ComponentIndexToFloat(color, idx);
96     return { outR, outG, outB, outA };
97 }
98 
ComponentIndexToFloat(std::array<float,4> color,int idx)99 constexpr float Swizzle::ComponentIndexToFloat(std::array<float, 4> color, int idx) {
100     if (idx <= 3) {
101         return color[idx];
102     }
103     if (idx == CToI('1')) {
104         return 1.0f;
105     }
106     if (idx == CToI('0')) {
107         return 0.0f;
108     }
109     SkUNREACHABLE;
110 }
111 
CToI(char c)112 constexpr int Swizzle::CToI(char c) {
113     switch (c) {
114         // r...a must map to 0...3 because other methods use them as indices into fSwiz.
115         case 'r': return 0;
116         case 'g': return 1;
117         case 'b': return 2;
118         case 'a': return 3;
119         case '0': return 4;
120         case '1': return 5;
121         default:  SkUNREACHABLE;
122     }
123 }
124 
IToC(int idx)125 constexpr char Swizzle::IToC(int idx) {
126     switch (idx) {
127         case CToI('r'): return 'r';
128         case CToI('g'): return 'g';
129         case CToI('b'): return 'b';
130         case CToI('a'): return 'a';
131         case CToI('0'): return '0';
132         case CToI('1'): return '1';
133         default:        SkUNREACHABLE;
134     }
135 }
136 
Concat(const Swizzle & a,const Swizzle & b)137 constexpr Swizzle Swizzle::Concat(const Swizzle& a, const Swizzle& b) {
138     uint16_t key = 0;
139     for (int i = 0; i < 4; ++i) {
140         int idx = (b.fKey >> (4U * i)) & 0xfU;
141         if (idx != CToI('0') && idx != CToI('1')) {
142             SkASSERT(idx >= 0 && idx < 4);
143             // Get the index value stored in a at location idx.
144             idx = ((a.fKey >> (4U * idx)) & 0xfU);
145         }
146         key |= (idx << (4U * i));
147     }
148     return Swizzle(key);
149 }
150 
151 } // namespace skgpu
152 #endif
153