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