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 "GrColor.h"
12 #include "SkColorData.h"
13 
14 /** Represents a rgba swizzle. It can be converted either into a string or a eight bit int.
15     Currently there is no way to specify an arbitrary swizzle, just some static swizzles and an
16     assignment operator. That could be relaxed. */
17 class GrSwizzle {
18 public:
GrSwizzle()19     constexpr GrSwizzle() : GrSwizzle("rgba") {}
20 
GrSwizzle(const GrSwizzle & that)21     constexpr GrSwizzle(const GrSwizzle& that)
22             : fSwiz{that.fSwiz[0], that.fSwiz[1], that.fSwiz[2], that.fSwiz[3], '\0'}
23             , fKey(that.fKey) {}
24 
25     constexpr GrSwizzle& operator=(const GrSwizzle& that) {
26         fSwiz[0] = that.fSwiz[0];
27         fSwiz[1] = that.fSwiz[1];
28         fSwiz[2] = that.fSwiz[2];
29         fSwiz[3] = that.fSwiz[3];
30         SkASSERT(fSwiz[4] == '\0');
31         fKey = that.fKey;
32         return *this;
33     }
34 
35     /** Recreates a GrSwizzle from the output of asKey() */
setFromKey(uint8_t key)36     constexpr void setFromKey(uint8_t key) {
37         fKey = key;
38         for (int i = 0; i < 4; ++i) {
39             fSwiz[i] = IToC(key & 3);
40             key >>= 2;
41         }
42         SkASSERT(fSwiz[4] == 0);
43     }
44 
45     constexpr bool operator==(const GrSwizzle& that) const { return fKey == that.fKey; }
46     constexpr bool operator!=(const GrSwizzle& that) const { return !(*this == that); }
47 
48     /** Compact representation of the swizzle suitable for a key. */
asKey()49     constexpr uint8_t asKey() const { return fKey; }
50 
51     /** 4 char null terminated string consisting only of chars 'r', 'g', 'b', 'a'. */
c_str()52     const char* c_str() const { return fSwiz; }
53 
54     char operator[](int i) const {
55         SkASSERT(i >= 0 && i < 4);
56         return fSwiz[i];
57     }
58 
59     /** Applies this swizzle to the input color and returns the swizzled color. */
applyTo(const SkPMColor4f & color)60     SkPMColor4f applyTo(const SkPMColor4f& color) const {
61         int idx;
62         uint32_t key = fKey;
63         // Index of the input color that should be mapped to output r.
64         idx = (key & 3);
65         float outR = color[idx];
66         key >>= 2;
67         idx = (key & 3);
68         float outG = color[idx];
69         key >>= 2;
70         idx = (key & 3);
71         float outB = color[idx];
72         key >>= 2;
73         idx = (key & 3);
74         float outA = color[idx];
75         return { outR, outG, outB, outA };
76     }
77 
RGBA()78     static constexpr GrSwizzle RGBA() { return GrSwizzle("rgba"); }
AAAA()79     static constexpr GrSwizzle AAAA() { return GrSwizzle("aaaa"); }
RRRR()80     static constexpr GrSwizzle RRRR() { return GrSwizzle("rrrr"); }
RRRA()81     static constexpr GrSwizzle RRRA() { return GrSwizzle("rrra"); }
BGRA()82     static constexpr GrSwizzle BGRA() { return GrSwizzle("bgra"); }
RGRG()83     static constexpr GrSwizzle RGRG() { return GrSwizzle("rgrg"); }
84 
85 private:
86     char fSwiz[5];
87     uint8_t fKey;
88 
CToI(char c)89     static constexpr int CToI(char c) {
90         switch (c) {
91             case 'r': return (GrColor_SHIFT_R / 8);
92             case 'g': return (GrColor_SHIFT_G / 8);
93             case 'b': return (GrColor_SHIFT_B / 8);
94             case 'a': return (GrColor_SHIFT_A / 8);
95             default:  return -1;
96         }
97     }
98 
IToC(int idx)99     static constexpr char IToC(int idx) {
100         switch (8 * idx) {
101             case GrColor_SHIFT_R : return 'r';
102             case GrColor_SHIFT_G : return 'g';
103             case GrColor_SHIFT_B : return 'b';
104             case GrColor_SHIFT_A : return 'a';
105             default:               return -1;
106         }
107     }
108 
GrSwizzle(const char c[4])109     constexpr GrSwizzle(const char c[4])
110             : fSwiz{c[0], c[1], c[2], c[3], '\0'}
111             , fKey((CToI(c[0]) << 0) | (CToI(c[1]) << 2) | (CToI(c[2]) << 4) | (CToI(c[3]) << 6)) {}
112 };
113 
114 #endif
115