blob: a250842d6b4dd325e999958ec015c60a06a5b2c1 [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
Greg Daniel369ee6b2019-12-02 15:30:02 -050011#include "include/core/SkString.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#include "include/private/SkColorData.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040013#include "src/gpu/GrColor.h"
bsalomoncdee0092016-01-08 13:20:12 -080014
Brian Salomon217522c2019-06-11 15:55:30 -040015class SkRasterPipeline;
16
17/** Represents a rgba swizzle. It can be converted either into a string or a eight bit int. */
bsalomoncdee0092016-01-08 13:20:12 -080018class GrSwizzle {
19public:
Brian Salomon21511652018-10-17 08:30:51 -040020 constexpr GrSwizzle() : GrSwizzle("rgba") {}
Brian Salomon217522c2019-06-11 15:55:30 -040021 explicit constexpr GrSwizzle(const char c[4]);
bsalomoncdee0092016-01-08 13:20:12 -080022
Brian Salomon217522c2019-06-11 15:55:30 -040023 constexpr GrSwizzle(const GrSwizzle&);
24 constexpr GrSwizzle& operator=(const GrSwizzle& that);
bsalomoncdee0092016-01-08 13:20:12 -080025
Brian Salomonf30b1c12019-06-20 12:25:02 -040026 static constexpr GrSwizzle Concat(const GrSwizzle& a, const GrSwizzle& b);
27
Brian Salomon21511652018-10-17 08:30:51 -040028 constexpr bool operator==(const GrSwizzle& that) const { return fKey == that.fKey; }
29 constexpr bool operator!=(const GrSwizzle& that) const { return !(*this == that); }
bsalomoncdee0092016-01-08 13:20:12 -080030
31 /** Compact representation of the swizzle suitable for a key. */
Greg Danielf259b8b2019-02-14 09:03:43 -050032 constexpr uint16_t asKey() const { return fKey; }
bsalomoncdee0092016-01-08 13:20:12 -080033
Brian Salomonf30b1c12019-06-20 12:25:02 -040034 /** 4 char null terminated string consisting only of chars 'r', 'g', 'b', 'a', '0', and '1'. */
Greg Daniel369ee6b2019-12-02 15:30:02 -050035 SkString asString() const;
bsalomoncdee0092016-01-08 13:20:12 -080036
Brian Salomon217522c2019-06-11 15:55:30 -040037 constexpr char operator[](int i) const {
Brian Salomondc829942018-10-23 16:07:24 -040038 SkASSERT(i >= 0 && i < 4);
Greg Daniel369ee6b2019-12-02 15:30:02 -050039 int idx = (fKey >> (4U * i)) & 0xfU;
40 return IToC(idx);
Brian Salomondc829942018-10-23 16:07:24 -040041 }
42
bsalomon7f9b2e42016-01-12 13:29:26 -080043 /** Applies this swizzle to the input color and returns the swizzled color. */
Brian Salomonb450f3b2019-07-09 09:36:51 -040044 template <SkAlphaType AlphaType>
45 constexpr SkRGBA4f<AlphaType> applyTo(const SkRGBA4f<AlphaType>& color) const;
Brian Salomon217522c2019-06-11 15:55:30 -040046
47 void apply(SkRasterPipeline*) const;
Brian Osmance425512017-03-22 14:37:50 -040048
Brian Salomon21511652018-10-17 08:30:51 -040049 static constexpr GrSwizzle RGBA() { return GrSwizzle("rgba"); }
50 static constexpr GrSwizzle AAAA() { return GrSwizzle("aaaa"); }
51 static constexpr GrSwizzle RRRR() { return GrSwizzle("rrrr"); }
52 static constexpr GrSwizzle RRRA() { return GrSwizzle("rrra"); }
53 static constexpr GrSwizzle BGRA() { return GrSwizzle("bgra"); }
Greg Danielf259b8b2019-02-14 09:03:43 -050054 static constexpr GrSwizzle RGB1() { return GrSwizzle("rgb1"); }
bsalomoncdee0092016-01-08 13:20:12 -080055
Brian Salomon21511652018-10-17 08:30:51 -040056private:
Greg Daniel369ee6b2019-12-02 15:30:02 -050057 explicit constexpr GrSwizzle(uint16_t key) : fKey(key) {}
58
Brian Salomonb450f3b2019-07-09 09:36:51 -040059 template <SkAlphaType AlphaType>
60 static constexpr float ComponentIndexToFloat(const SkRGBA4f<AlphaType>& color, int idx);
Brian Salomon217522c2019-06-11 15:55:30 -040061 static constexpr int CToI(char c);
62 static constexpr char IToC(int idx);
63
Greg Danielf259b8b2019-02-14 09:03:43 -050064 uint16_t fKey;
bsalomoncdee0092016-01-08 13:20:12 -080065};
66
Brian Salomon217522c2019-06-11 15:55:30 -040067constexpr GrSwizzle::GrSwizzle(const char c[4])
Greg Daniel369ee6b2019-12-02 15:30:02 -050068 : fKey((CToI(c[0]) << 0) | (CToI(c[1]) << 4) | (CToI(c[2]) << 8) | (CToI(c[3]) << 12)) {}
Brian Salomon217522c2019-06-11 15:55:30 -040069
70constexpr GrSwizzle::GrSwizzle(const GrSwizzle& that)
Greg Daniel369ee6b2019-12-02 15:30:02 -050071 : fKey(that.fKey) {}
Brian Salomon217522c2019-06-11 15:55:30 -040072
73constexpr GrSwizzle& GrSwizzle::operator=(const GrSwizzle& that) {
Brian Salomon217522c2019-06-11 15:55:30 -040074 fKey = that.fKey;
75 return *this;
76}
77
Brian Salomonb450f3b2019-07-09 09:36:51 -040078template <SkAlphaType AlphaType>
79constexpr SkRGBA4f<AlphaType> GrSwizzle::applyTo(const SkRGBA4f<AlphaType>& color) const {
Brian Salomon217522c2019-06-11 15:55:30 -040080 uint32_t key = fKey;
81 // Index of the input color that should be mapped to output r.
82 int idx = (key & 15);
83 float outR = ComponentIndexToFloat(color, idx);
84 key >>= 4;
85 idx = (key & 15);
86 float outG = ComponentIndexToFloat(color, idx);
87 key >>= 4;
88 idx = (key & 15);
89 float outB = ComponentIndexToFloat(color, idx);
90 key >>= 4;
91 idx = (key & 15);
92 float outA = ComponentIndexToFloat(color, idx);
93 return { outR, outG, outB, outA };
94}
95
Brian Salomonb450f3b2019-07-09 09:36:51 -040096template <SkAlphaType AlphaType>
97constexpr float GrSwizzle::ComponentIndexToFloat(const SkRGBA4f<AlphaType>& color, int idx) {
Brian Salomon217522c2019-06-11 15:55:30 -040098 if (idx <= 3) {
99 return color[idx];
100 }
Brian Salomonf30b1c12019-06-20 12:25:02 -0400101 if (idx == CToI('1')) {
Brian Salomon217522c2019-06-11 15:55:30 -0400102 return 1.0f;
103 }
Brian Salomonf30b1c12019-06-20 12:25:02 -0400104 if (idx == CToI('0')) {
105 return 1.0f;
106 }
Brian Salomon24fc4eb2019-06-26 14:15:36 -0400107 SkUNREACHABLE;
Brian Salomon217522c2019-06-11 15:55:30 -0400108}
109
110constexpr int GrSwizzle::CToI(char c) {
111 switch (c) {
Brian Salomonf30b1c12019-06-20 12:25:02 -0400112 // r...a must map to 0...3 because other methods use them as indices into fSwiz.
113 case 'r': return 0;
114 case 'g': return 1;
115 case 'b': return 2;
116 case 'a': return 3;
117 case '0': return 4;
118 case '1': return 5;
Brian Salomon24fc4eb2019-06-26 14:15:36 -0400119 default: SkUNREACHABLE;
Brian Salomon217522c2019-06-11 15:55:30 -0400120 }
121}
122
123constexpr char GrSwizzle::IToC(int idx) {
Brian Salomonf30b1c12019-06-20 12:25:02 -0400124 switch (idx) {
125 case CToI('r'): return 'r';
126 case CToI('g'): return 'g';
127 case CToI('b'): return 'b';
128 case CToI('a'): return 'a';
129 case CToI('0'): return '0';
130 case CToI('1'): return '1';
Brian Salomon24fc4eb2019-06-26 14:15:36 -0400131 default: SkUNREACHABLE;
Brian Salomon217522c2019-06-11 15:55:30 -0400132 }
133}
134
Brian Salomonf30b1c12019-06-20 12:25:02 -0400135constexpr GrSwizzle GrSwizzle::Concat(const GrSwizzle& a, const GrSwizzle& b) {
Greg Daniel369ee6b2019-12-02 15:30:02 -0500136 uint16_t key = 0;
Brian Salomonf30b1c12019-06-20 12:25:02 -0400137 for (int i = 0; i < 4; ++i) {
138 int idx = (b.fKey >> (4U * i)) & 0xfU;
Greg Daniel369ee6b2019-12-02 15:30:02 -0500139 if (idx != CToI('0') && idx != CToI('1')) {
140 SkASSERT(idx >= 0 && idx < 4);
141 // Get the index value stored in a at location idx.
142 idx = ((a.fKey >> (4U * idx)) & 0xfU);
Brian Salomonf30b1c12019-06-20 12:25:02 -0400143 }
Greg Daniel369ee6b2019-12-02 15:30:02 -0500144 key |= (idx << (4U * i));
Brian Salomonf30b1c12019-06-20 12:25:02 -0400145 }
Greg Daniel369ee6b2019-12-02 15:30:02 -0500146 return GrSwizzle(key);
Brian Salomonf30b1c12019-06-20 12:25:02 -0400147}
bsalomoncdee0092016-01-08 13:20:12 -0800148#endif