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