9
9
10
10
namespace flutter {
11
11
12
+ // These should match the enumerations defined in //lib/ui/painting.dart.
13
+ enum class DlColorSpace { kSRGB = 0 , kExtendedSRGB = 1 , kDisplayP3 = 2 };
14
+
15
+ // / A representation of a color.
16
+ // /
17
+ // / The color belongs to a DlColorSpace. Using deprecated integer data accessors
18
+ // / on colors not in the kSRGB colorspace can lead to data loss. Using the
19
+ // / floating point accessors and constructors that were added for wide-gamut
20
+ // / support are preferred.
12
21
struct DlColor {
13
22
public:
14
- constexpr DlColor () : argb_(0xFF000000 ) {}
15
- constexpr explicit DlColor (uint32_t argb) : argb_(argb) {}
23
+ constexpr DlColor ()
24
+ : alpha_(0 .f),
25
+ red_(0 .f),
26
+ green_(0 .f),
27
+ blue_(0 .f),
28
+ color_space_(DlColorSpace::kSRGB ) {}
29
+ constexpr explicit DlColor (uint32_t argb)
30
+ : alpha_(toF((argb >> 24 ) & 0xff)),
31
+ red_(toF((argb >> 16 ) & 0xff)),
32
+ green_(toF((argb >> 8 ) & 0xff)),
33
+ blue_(toF((argb >> 0 ) & 0xff)),
34
+ color_space_(DlColorSpace::kSRGB ) {}
35
+ constexpr DlColor (DlScalar alpha,
36
+ DlScalar red,
37
+ DlScalar green,
38
+ DlScalar blue,
39
+ DlColorSpace colorspace)
40
+ : alpha_(alpha),
41
+ red_(red),
42
+ green_(green),
43
+ blue_(blue),
44
+ color_space_(colorspace) {}
16
45
17
46
// / @brief Construct a 32 bit color from floating point R, G, B, and A color
18
47
// / channels.
@@ -29,10 +58,7 @@ struct DlColor {
29
58
DlScalar r,
30
59
DlScalar g,
31
60
DlScalar b) {
32
- return DlColor (toC (a) << 24 | //
33
- toC (r) << 16 | //
34
- toC (g) << 8 | //
35
- toC (b));
61
+ return DlColor (a, r, g, b, DlColorSpace::kSRGB );
36
62
}
37
63
38
64
static constexpr uint8_t toAlpha (DlScalar opacity) { return toC (opacity); }
@@ -66,58 +92,106 @@ struct DlColor {
66
92
static constexpr DlColor kOrangeRed () {return DlColor (0xFFFF4500 );};
67
93
// clang-format on
68
94
69
- constexpr bool isOpaque () const { return getAlpha () == 0xFF ; }
70
- constexpr bool isTransparent () const { return getAlpha () == 0 ; }
71
-
72
- constexpr int getAlpha () const { return argb_ >> 24 ; }
73
- constexpr int getRed () const { return (argb_ >> 16 ) & 0xFF ; }
74
- constexpr int getGreen () const { return (argb_ >> 8 ) & 0xFF ; }
75
- constexpr int getBlue () const { return argb_ & 0xFF ; }
76
-
77
- constexpr DlScalar getAlphaF () const { return toF (getAlpha ()); }
78
- constexpr DlScalar getRedF () const { return toF (getRed ()); }
79
- constexpr DlScalar getGreenF () const { return toF (getGreen ()); }
80
- constexpr DlScalar getBlueF () const { return toF (getBlue ()); }
81
-
82
- constexpr uint32_t premultipliedArgb () const {
83
- if (isOpaque ()) {
84
- return argb_;
85
- }
86
- DlScalar f = getAlphaF ();
87
- return (argb_ & 0xFF000000 ) | //
88
- toC (getRedF () * f) << 16 | //
89
- toC (getGreenF () * f) << 8 | //
90
- toC (getBlueF () * f);
91
- }
95
+ constexpr bool isOpaque () const { return alpha_ >= 1 .f ; }
96
+ constexpr bool isTransparent () const { return alpha_ <= 0 .f ; }
97
+
98
+ // /\deprecated Use floating point accessors to avoid data loss when using wide
99
+ // / gamut colors.
100
+ constexpr int getAlpha () const { return toC (alpha_); }
101
+ // /\deprecated Use floating point accessors to avoid data loss when using wide
102
+ // / gamut colors.
103
+ constexpr int getRed () const { return toC (red_); }
104
+ // /\deprecated Use floating point accessors to avoid data loss when using wide
105
+ // / gamut colors.
106
+ constexpr int getGreen () const { return toC (green_); }
107
+ // /\deprecated Use floating point accessors to avoid data loss when using wide
108
+ // / gamut colors.
109
+ constexpr int getBlue () const { return toC (blue_); }
110
+
111
+ constexpr DlScalar getAlphaF () const { return alpha_; }
112
+ constexpr DlScalar getRedF () const { return red_; }
113
+ constexpr DlScalar getGreenF () const { return green_; }
114
+ constexpr DlScalar getBlueF () const { return blue_; }
115
+
116
+ constexpr DlColorSpace getColorSpace () const { return color_space_; }
92
117
93
118
constexpr DlColor withAlpha (uint8_t alpha) const { //
94
- return DlColor ((argb_ & 0x00FFFFFF ) | (alpha << 24 ));
119
+ return DlColor ((argb () & 0x00FFFFFF ) | (alpha << 24 ));
95
120
}
96
121
constexpr DlColor withRed (uint8_t red) const { //
97
- return DlColor ((argb_ & 0xFF00FFFF ) | (red << 16 ));
122
+ return DlColor ((argb () & 0xFF00FFFF ) | (red << 16 ));
98
123
}
99
124
constexpr DlColor withGreen (uint8_t green) const { //
100
- return DlColor ((argb_ & 0xFFFF00FF ) | (green << 8 ));
125
+ return DlColor ((argb () & 0xFFFF00FF ) | (green << 8 ));
101
126
}
102
127
constexpr DlColor withBlue (uint8_t blue) const { //
103
- return DlColor ((argb_ & 0xFFFFFF00 ) | (blue << 0 ));
128
+ return DlColor ((argb () & 0xFFFFFF00 ) | (blue << 0 ));
129
+ }
130
+ constexpr DlColor withAlphaF (float alpha) const { //
131
+ return DlColor (alpha, red_, green_, blue_, color_space_);
132
+ }
133
+ constexpr DlColor withRedF (float red) const { //
134
+ return DlColor (alpha_, red, green_, blue_, color_space_);
135
+ }
136
+ constexpr DlColor withGreenF (float green) const { //
137
+ return DlColor (alpha_, red_, green, blue_, color_space_);
104
138
}
139
+ constexpr DlColor withBlueF (float blue) const { //
140
+ return DlColor (alpha_, red_, green_, blue, color_space_);
141
+ }
142
+ // / Performs a colorspace transformation.
143
+ // /
144
+ // / This isn't just a replacement of the color space field, the new color
145
+ // / components are calculated.
146
+ DlColor withColorSpace (DlColorSpace color_space) const ;
105
147
106
148
constexpr DlColor modulateOpacity (DlScalar opacity) const {
107
149
return opacity <= 0 ? withAlpha (0 )
108
150
: opacity >= 1 ? *this
109
151
: withAlpha (round (getAlpha () * opacity));
110
152
}
111
153
112
- constexpr uint32_t argb () const { return argb_; }
154
+ // /\deprecated Use floating point accessors to avoid data loss when using wide
155
+ // / gamut colors.
156
+ constexpr uint32_t argb () const {
157
+ return toC (alpha_) << 24 | //
158
+ toC (red_) << 16 | //
159
+ toC (green_) << 8 | //
160
+ toC (blue_) << 0 ;
161
+ }
113
162
114
- bool operator ==(DlColor const & other) const { return argb_ == other.argb_ ; }
115
- bool operator !=(DlColor const & other) const { return argb_ != other.argb_ ; }
116
- bool operator ==(uint32_t const & other) const { return argb_ == other; }
117
- bool operator !=(uint32_t const & other) const { return argb_ != other; }
163
+ // / Checks that no difference in color components exceeds the delta.
164
+ // /
165
+ // / This doesn't check against the actual distance between the colors in some
166
+ // / space.
167
+ bool isClose (DlColor const & other, DlScalar delta = 1 .0f / 256 .0f ) {
168
+ return color_space_ == other.color_space_ &&
169
+ std::abs (alpha_ - other.alpha_ ) < delta &&
170
+ std::abs (red_ - other.red_ ) < delta &&
171
+ std::abs (green_ - other.green_ ) < delta &&
172
+ std::abs (blue_ - other.blue_ ) < delta;
173
+ }
174
+ bool operator ==(DlColor const & other) const {
175
+ return alpha_ == other.alpha_ && red_ == other.red_ &&
176
+ green_ == other.green_ && blue_ == other.blue_ &&
177
+ color_space_ == other.color_space_ ;
178
+ }
179
+ bool operator !=(DlColor const & other) const {
180
+ return !this ->operator ==(other);
181
+ }
182
+ bool operator ==(uint32_t const & other) const {
183
+ return argb () == other && color_space_ == DlColorSpace::kSRGB ;
184
+ }
185
+ bool operator !=(uint32_t const & other) const {
186
+ return !this ->operator ==(other);
187
+ }
118
188
119
189
private:
120
- uint32_t argb_;
190
+ DlScalar alpha_;
191
+ DlScalar red_;
192
+ DlScalar green_;
193
+ DlScalar blue_;
194
+ DlColorSpace color_space_;
121
195
122
196
static constexpr DlScalar toF (uint8_t comp) { return comp * (1 .0f / 255 ); }
123
197
static constexpr uint8_t toC (DlScalar fComp ) { return round (fComp * 255 ); }
0 commit comments