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(uint16_t key)36 constexpr void setFromKey(uint16_t key) { 37 fKey = key; 38 for (int i = 0; i < 4; ++i) { 39 fSwiz[i] = IToC(key & 15); 40 key >>= 4; 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 uint16_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 60 // The normal component swizzles map to key values 0-3. We set the key for constant 1 to the 61 // next int. 62 static const int k1KeyValue = 4; 63 component_idx_to_float(const SkPMColor4f & color,int idx)64 static float component_idx_to_float(const SkPMColor4f& color, int idx) { 65 if (idx <= 3) { 66 return color[idx]; 67 } 68 if (idx == k1KeyValue) { 69 return 1.0f; 70 } 71 SK_ABORT("Unexpected swizzle component indx"); 72 return -1.0f; 73 } 74 75 /** Applies this swizzle to the input color and returns the swizzled color. */ applyTo(const SkPMColor4f & color)76 SkPMColor4f applyTo(const SkPMColor4f& color) const { 77 int idx; 78 uint32_t key = fKey; 79 // Index of the input color that should be mapped to output r. 80 idx = (key & 15); 81 float outR = component_idx_to_float(color, idx); 82 key >>= 4; 83 idx = (key & 15); 84 float outG = component_idx_to_float(color, idx); 85 key >>= 4; 86 idx = (key & 15); 87 float outB = component_idx_to_float(color, idx); 88 key >>= 4; 89 idx = (key & 15); 90 float outA = component_idx_to_float(color, idx); 91 return { outR, outG, outB, outA }; 92 } 93 RGBA()94 static constexpr GrSwizzle RGBA() { return GrSwizzle("rgba"); } AAAA()95 static constexpr GrSwizzle AAAA() { return GrSwizzle("aaaa"); } RRRR()96 static constexpr GrSwizzle RRRR() { return GrSwizzle("rrrr"); } RRRA()97 static constexpr GrSwizzle RRRA() { return GrSwizzle("rrra"); } BGRA()98 static constexpr GrSwizzle BGRA() { return GrSwizzle("bgra"); } RGRG()99 static constexpr GrSwizzle RGRG() { return GrSwizzle("rgrg"); } RGB1()100 static constexpr GrSwizzle RGB1() { return GrSwizzle("rgb1"); } 101 102 private: 103 char fSwiz[5]; 104 uint16_t fKey; 105 CToI(char c)106 static constexpr int CToI(char c) { 107 switch (c) { 108 case 'r': return (GrColor_SHIFT_R / 8); 109 case 'g': return (GrColor_SHIFT_G / 8); 110 case 'b': return (GrColor_SHIFT_B / 8); 111 case 'a': return (GrColor_SHIFT_A / 8); 112 case '1': return k1KeyValue; 113 default: return -1; 114 } 115 } 116 IToC(int idx)117 static constexpr char IToC(int idx) { 118 switch (8 * idx) { 119 case GrColor_SHIFT_R : return 'r'; 120 case GrColor_SHIFT_G : return 'g'; 121 case GrColor_SHIFT_B : return 'b'; 122 case GrColor_SHIFT_A : return 'a'; 123 case (k1KeyValue * 8) : return '1'; 124 default: return -1; 125 } 126 } 127 GrSwizzle(const char c[4])128 constexpr GrSwizzle(const char c[4]) 129 : fSwiz{c[0], c[1], c[2], c[3], '\0'} 130 , fKey((CToI(c[0]) << 0) | (CToI(c[1]) << 4) | (CToI(c[2]) << 8) | (CToI(c[3]) << 12)) {} 131 }; 132 133 #endif 134