Line data Source code
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 "SkRandom.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 : private:
19 : char fSwiz[5];
20 : uint8_t fKey;
21 :
22 0 : static constexpr int CToI(char c) {
23 0 : return ('r' == c) ? (GrColor_SHIFT_R / 8) :
24 0 : ('g' == c) ? (GrColor_SHIFT_G / 8) :
25 0 : ('b' == c) ? (GrColor_SHIFT_B / 8) :
26 0 : ('a' == c) ? (GrColor_SHIFT_A / 8) : -1;
27 : }
28 :
29 0 : static constexpr char IToC(int idx) {
30 0 : return (8 * idx) == GrColor_SHIFT_R ? 'r' :
31 0 : (8 * idx) == GrColor_SHIFT_G ? 'g' :
32 0 : (8 * idx) == GrColor_SHIFT_B ? 'b' :
33 0 : (8 * idx) == GrColor_SHIFT_A ? 'a' : 'x';
34 : }
35 :
36 0 : constexpr GrSwizzle(const char c[4])
37 0 : : fSwiz{c[0], c[1], c[2], c[3], 0}
38 0 : , fKey((CToI(c[0]) << 0) | (CToI(c[1]) << 2) | (CToI(c[2]) << 4) | (CToI(c[3]) << 6)) {}
39 :
40 : GR_STATIC_ASSERT(sizeof(char[4]) == sizeof(uint32_t));
41 : uint32_t* asUIntPtr() { return SkTCast<uint32_t*>(fSwiz); }
42 0 : uint32_t asUInt() const { return *SkTCast<const uint32_t*>(fSwiz); }
43 :
44 : public:
45 0 : GrSwizzle() { *this = RGBA(); }
46 :
47 0 : GrSwizzle(const GrSwizzle& that) { *this = that; }
48 :
49 0 : GrSwizzle& operator=(const GrSwizzle& that) {
50 0 : memcpy(this, &that, sizeof(GrSwizzle));
51 0 : return *this;
52 : }
53 :
54 : /** Recreates a GrSwizzle from the output of asKey() */
55 0 : void setFromKey(uint8_t key) {
56 0 : fKey = key;
57 0 : for (int i = 0; i < 4; ++i) {
58 0 : fSwiz[i] = IToC(key & 3);
59 0 : key >>= 2;
60 : }
61 0 : SkASSERT(fSwiz[4] == 0);
62 0 : }
63 :
64 0 : bool operator==(const GrSwizzle& that) const { return this->asUInt() == that.asUInt(); }
65 :
66 0 : bool operator!=(const GrSwizzle& that) const { return !(*this == that); }
67 :
68 : /** Compact representation of the swizzle suitable for a key. */
69 0 : uint8_t asKey() const { return fKey; }
70 :
71 : /** 4 char null terminated string consisting only of chars 'r', 'g', 'b', 'a'. */
72 0 : const char* c_str() const { return fSwiz; }
73 :
74 : /** Applies this swizzle to the input color and returns the swizzled color. */
75 0 : GrColor applyTo(GrColor color) const {
76 : int idx;
77 0 : uint32_t key = fKey;
78 : // Index of the input color that should be mapped to output r.
79 0 : idx = (key & 3);
80 0 : uint32_t outR = (color >> idx * 8) & 0xFF;
81 0 : key >>= 2;
82 0 : idx = (key & 3);
83 0 : uint32_t outG = (color >> idx * 8) & 0xFF;
84 0 : key >>= 2;
85 0 : idx = (key & 3);
86 0 : uint32_t outB = (color >> idx * 8) & 0xFF;
87 0 : key >>= 2;
88 0 : idx = (key & 3);
89 0 : uint32_t outA = (color >> idx * 8) & 0xFF;
90 0 : return GrColorPackRGBA(outR, outG, outB, outA);
91 : }
92 :
93 : /** Applies this swizzle to the input color and returns the swizzled color. */
94 0 : GrColor4f applyTo(const GrColor4f& color) const {
95 : int idx;
96 0 : uint32_t key = fKey;
97 : // Index of the input color that should be mapped to output r.
98 0 : idx = (key & 3);
99 0 : float outR = color.fRGBA[idx];
100 0 : key >>= 2;
101 0 : idx = (key & 3);
102 0 : float outG = color.fRGBA[idx];
103 0 : key >>= 2;
104 0 : idx = (key & 3);
105 0 : float outB = color.fRGBA[idx];
106 0 : key >>= 2;
107 0 : idx = (key & 3);
108 0 : float outA = color.fRGBA[idx];
109 0 : return GrColor4f(outR, outG, outB, outA);
110 : }
111 :
112 0 : static GrSwizzle RGBA() { return GrSwizzle("rgba"); }
113 0 : static GrSwizzle AAAA() { return GrSwizzle("aaaa"); }
114 0 : static GrSwizzle RRRR() { return GrSwizzle("rrrr"); }
115 0 : static GrSwizzle RRRA() { return GrSwizzle("rrra"); }
116 0 : static GrSwizzle BGRA() { return GrSwizzle("bgra"); }
117 :
118 : static GrSwizzle CreateRandom(SkRandom* random) {
119 : switch (random->nextU() % 4) {
120 : case 0:
121 : return RGBA();
122 : case 1:
123 : return BGRA();
124 : case 2:
125 : return RRRR();
126 : case 3:
127 : return AAAA();
128 : default:
129 : SkFAIL("Mod is broken?!?");
130 : return RGBA();
131 : }
132 : }
133 : };
134 :
135 : #endif
|