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