blob: 469740b18726835747ed25a65a44b7a133693305 [file] [log] [blame]
bsalomoncdee0092016-01-08 13:20:12 -08001/*
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
bsalomon7f9b2e42016-01-12 13:29:26 -080011#include "GrColor.h"
Brian Osmane3f543c2018-11-02 12:52:10 -040012#include "SkColorData.h"
bsalomoncdee0092016-01-08 13:20:12 -080013
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. */
17class GrSwizzle {
18public:
Brian Salomon21511652018-10-17 08:30:51 -040019 constexpr GrSwizzle() : GrSwizzle("rgba") {}
bsalomoncdee0092016-01-08 13:20:12 -080020
Brian Salomon21511652018-10-17 08:30:51 -040021 constexpr GrSwizzle(const GrSwizzle& that)
22 : fSwiz{that.fSwiz[0], that.fSwiz[1], that.fSwiz[2], that.fSwiz[3], '\0'}
23 , fKey(that.fKey) {}
bsalomon7f9b2e42016-01-12 13:29:26 -080024
Brian Salomon21511652018-10-17 08:30:51 -040025 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;
bsalomoncdee0092016-01-08 13:20:12 -080032 return *this;
33 }
34
bsalomon7f9b2e42016-01-12 13:29:26 -080035 /** Recreates a GrSwizzle from the output of asKey() */
Greg Danielf259b8b2019-02-14 09:03:43 -050036 constexpr void setFromKey(uint16_t key) {
bsalomon7f9b2e42016-01-12 13:29:26 -080037 fKey = key;
38 for (int i = 0; i < 4; ++i) {
Greg Danielf259b8b2019-02-14 09:03:43 -050039 fSwiz[i] = IToC(key & 15);
40 key >>= 4;
bsalomon7f9b2e42016-01-12 13:29:26 -080041 }
42 SkASSERT(fSwiz[4] == 0);
43 }
44
Brian Salomon21511652018-10-17 08:30:51 -040045 constexpr bool operator==(const GrSwizzle& that) const { return fKey == that.fKey; }
46 constexpr bool operator!=(const GrSwizzle& that) const { return !(*this == that); }
bsalomoncdee0092016-01-08 13:20:12 -080047
48 /** Compact representation of the swizzle suitable for a key. */
Greg Danielf259b8b2019-02-14 09:03:43 -050049 constexpr uint16_t asKey() const { return fKey; }
bsalomoncdee0092016-01-08 13:20:12 -080050
51 /** 4 char null terminated string consisting only of chars 'r', 'g', 'b', 'a'. */
52 const char* c_str() const { return fSwiz; }
53
Brian Salomondc829942018-10-23 16:07:24 -040054 char operator[](int i) const {
55 SkASSERT(i >= 0 && i < 4);
56 return fSwiz[i];
57 }
58
Greg Danielf259b8b2019-02-14 09:03:43 -050059
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
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
bsalomon7f9b2e42016-01-12 13:29:26 -080075 /** Applies this swizzle to the input color and returns the swizzled color. */
Brian Osman1d5b5982018-10-01 13:41:39 -040076 SkPMColor4f applyTo(const SkPMColor4f& color) const {
Brian Osmance425512017-03-22 14:37:50 -040077 int idx;
78 uint32_t key = fKey;
79 // Index of the input color that should be mapped to output r.
Greg Danielf259b8b2019-02-14 09:03:43 -050080 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);
Brian Osman1d5b5982018-10-01 13:41:39 -040091 return { outR, outG, outB, outA };
Brian Osmance425512017-03-22 14:37:50 -040092 }
93
Brian Salomon21511652018-10-17 08:30:51 -040094 static constexpr GrSwizzle RGBA() { return GrSwizzle("rgba"); }
95 static constexpr GrSwizzle AAAA() { return GrSwizzle("aaaa"); }
96 static constexpr GrSwizzle RRRR() { return GrSwizzle("rrrr"); }
97 static constexpr GrSwizzle RRRA() { return GrSwizzle("rrra"); }
98 static constexpr GrSwizzle BGRA() { return GrSwizzle("bgra"); }
Jim Van Verth69e57852018-12-05 13:38:59 -050099 static constexpr GrSwizzle RGRG() { return GrSwizzle("rgrg"); }
Greg Danielf259b8b2019-02-14 09:03:43 -0500100 static constexpr GrSwizzle RGB1() { return GrSwizzle("rgb1"); }
bsalomoncdee0092016-01-08 13:20:12 -0800101
Brian Salomon21511652018-10-17 08:30:51 -0400102private:
103 char fSwiz[5];
Greg Danielf259b8b2019-02-14 09:03:43 -0500104 uint16_t fKey;
Brian Salomon21511652018-10-17 08:30:51 -0400105
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);
Greg Danielf259b8b2019-02-14 09:03:43 -0500112 case '1': return k1KeyValue;
Brian Salomon21511652018-10-17 08:30:51 -0400113 default: return -1;
bsalomon6c9cd552016-01-22 07:17:34 -0800114 }
115 }
Brian Salomon21511652018-10-17 08:30:51 -0400116
117 static constexpr char IToC(int idx) {
118 switch (8 * idx) {
Greg Danielf259b8b2019-02-14 09:03:43 -0500119 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;
Brian Salomon21511652018-10-17 08:30:51 -0400125 }
126 }
127
128 constexpr GrSwizzle(const char c[4])
129 : fSwiz{c[0], c[1], c[2], c[3], '\0'}
Greg Danielf259b8b2019-02-14 09:03:43 -0500130 , fKey((CToI(c[0]) << 0) | (CToI(c[1]) << 4) | (CToI(c[2]) << 8) | (CToI(c[3]) << 12)) {}
bsalomoncdee0092016-01-08 13:20:12 -0800131};
132
133#endif