5
5
6
6
use crate :: {
7
7
color:: { add_alpha, fixup_hues_for_interpolate, split_alpha} ,
8
- AlphaColor , ColorSpace , ColorSpaceLayout , ColorSpaceTag , HueDirection , LinearSrgb , Missing ,
8
+ AlphaColor , ColorSpace , ColorSpaceLayout , ColorSpaceTag , Flags , HueDirection , LinearSrgb ,
9
+ Missing ,
9
10
} ;
10
11
11
12
/// A color with a color space tag decided at runtime.
@@ -29,8 +30,9 @@ use crate::{
29
30
pub struct DynamicColor {
30
31
/// The color space.
31
32
pub cs : ColorSpaceTag ,
32
- /// A bitmask of missing components.
33
- pub missing : Missing ,
33
+ /// The state of this color, tracking whether it has missing components and how it was
34
+ /// constructed. See the documentation of [`Flags`] for more information.
35
+ pub flags : Flags ,
34
36
/// The components.
35
37
///
36
38
/// The first three components are interpreted according to the
@@ -39,6 +41,11 @@ pub struct DynamicColor {
39
41
pub components : [ f32 ; 4 ] ,
40
42
}
41
43
44
+ // `DynamicColor` was carefully packed. Ensure its size doesn't accidentally change.
45
+ const _: ( ) = if size_of :: < DynamicColor > ( ) != 20 {
46
+ panic ! ( "`DynamicColor` size changed" ) ;
47
+ } ;
48
+
42
49
/// An intermediate struct used for interpolating between colors.
43
50
///
44
51
/// This is the return value of [`DynamicColor::interpolate`].
@@ -75,7 +82,7 @@ impl DynamicColor {
75
82
if let Some ( cs) = CS :: TAG {
76
83
Self {
77
84
cs,
78
- missing : Missing :: default ( ) ,
85
+ flags : Flags :: default ( ) ,
79
86
components : color. components ,
80
87
}
81
88
} else {
@@ -95,33 +102,36 @@ impl DynamicColor {
95
102
let ( opaque, alpha) = split_alpha ( self . components ) ;
96
103
let mut components = add_alpha ( self . cs . convert ( cs, opaque) , alpha) ;
97
104
// Reference: §12.2 of Color 4 spec
98
- let missing = if ! self . missing . is_empty ( ) {
105
+ let missing = if self . flags . has_missing ( ) {
99
106
if self . cs . same_analogous ( cs) {
100
107
for ( i, component) in components. iter_mut ( ) . enumerate ( ) {
101
- if self . missing . contains ( i) {
108
+ if self . flags . missing ( i) {
102
109
* component = 0.0 ;
103
110
}
104
111
}
105
- self . missing
112
+ Flags :: from_missing ( self . flags . extract_missing ( ) )
106
113
} else {
107
- let mut missing = self . missing & Missing :: single ( 3 ) ;
108
- if self . cs . h_missing ( self . missing ) {
109
- cs. set_h_missing ( & mut missing, & mut components) ;
114
+ let mut flags = Flags :: from_missing (
115
+ self . flags . extract_missing ( )
116
+ & Flags :: from_single_missing ( 3 ) . extract_missing ( ) ,
117
+ ) ;
118
+ if self . cs . h_missing ( self . flags ) {
119
+ cs. set_h_missing ( & mut flags, & mut components) ;
110
120
}
111
- if self . cs . c_missing ( self . missing ) {
112
- cs. set_c_missing ( & mut missing , & mut components) ;
121
+ if self . cs . c_missing ( self . flags ) {
122
+ cs. set_c_missing ( & mut flags , & mut components) ;
113
123
}
114
- if self . cs . l_missing ( self . missing ) {
115
- cs. set_l_missing ( & mut missing , & mut components) ;
124
+ if self . cs . l_missing ( self . flags ) {
125
+ cs. set_l_missing ( & mut flags , & mut components) ;
116
126
}
117
- missing
127
+ Flags :: from_missing ( self . flags . extract_missing ( ) )
118
128
}
119
129
} else {
120
- Missing :: default ( )
130
+ Flags :: default ( )
121
131
} ;
122
132
let mut result = Self {
123
133
cs,
124
- missing,
134
+ flags : missing,
125
135
components,
126
136
} ;
127
137
result. powerless_to_missing ( ) ;
@@ -135,9 +145,9 @@ impl DynamicColor {
135
145
/// a corresponding component which is 0. This method restores that
136
146
/// invariant after manipulation which might invalidate it.
137
147
fn zero_missing_components ( mut self ) -> Self {
138
- if ! self . missing . is_empty ( ) {
148
+ if self . flags . has_missing ( ) {
139
149
for ( i, component) in self . components . iter_mut ( ) . enumerate ( ) {
140
- if self . missing . contains ( i) {
150
+ if self . flags . missing ( i) {
141
151
* component = 0.0 ;
142
152
}
143
153
}
@@ -154,7 +164,7 @@ impl DynamicColor {
154
164
let components = self . cs . scale_chroma ( opaque, scale) ;
155
165
Self {
156
166
cs : self . cs ,
157
- missing : self . missing ,
167
+ flags : self . flags ,
158
168
components : add_alpha ( components, alpha) ,
159
169
}
160
170
. zero_missing_components ( )
@@ -171,15 +181,15 @@ impl DynamicColor {
171
181
let alpha = alpha. clamp ( 0. , 1. ) ;
172
182
Self {
173
183
cs : self . cs ,
174
- missing : self . missing ,
184
+ flags : self . flags ,
175
185
components : add_alpha ( components, alpha) ,
176
186
}
177
187
}
178
188
179
189
fn premultiply_split ( self ) -> ( [ f32 ; 3 ] , f32 ) {
180
190
// Reference: §12.3 of Color 4 spec
181
191
let ( opaque, alpha) = split_alpha ( self . components ) ;
182
- let premul = if alpha == 1.0 || self . missing . contains ( 3 ) {
192
+ let premul = if alpha == 1.0 || self . flags . missing ( 3 ) {
183
193
opaque
184
194
} else {
185
195
self . cs . layout ( ) . scale ( opaque, alpha)
@@ -195,8 +205,7 @@ impl DynamicColor {
195
205
if self . cs . layout ( ) != ColorSpaceLayout :: Rectangular
196
206
&& self . components [ 1 ] < POWERLESS_EPSILON
197
207
{
198
- self . cs
199
- . set_h_missing ( & mut self . missing , & mut self . components ) ;
208
+ self . cs . set_h_missing ( & mut self . flags , & mut self . components ) ;
200
209
}
201
210
}
202
211
@@ -214,12 +223,14 @@ impl DynamicColor {
214
223
) -> Interpolator {
215
224
let mut a = self . convert ( cs) ;
216
225
let mut b = other. convert ( cs) ;
217
- let missing = a. missing & b. missing ;
218
- if self . missing != other. missing {
226
+ let a_missing = a. flags . extract_missing ( ) ;
227
+ let b_missing = b. flags . extract_missing ( ) ;
228
+ let missing = a_missing & b_missing;
229
+ if a_missing != b_missing {
219
230
for i in 0 ..4 {
220
- if ( a . missing & !b . missing ) . contains ( i) {
231
+ if ( a_missing & !b_missing ) . contains ( i) {
221
232
a. components [ i] = b. components [ i] ;
222
- } else if ( !a . missing & b . missing ) . contains ( i) {
233
+ } else if ( !a_missing & b_missing ) . contains ( i) {
223
234
b. components [ i] = a. components [ i] ;
224
235
}
225
236
}
@@ -262,7 +273,7 @@ impl DynamicColor {
262
273
let [ x, y, z, a] = self . components ;
263
274
Self {
264
275
cs : self . cs ,
265
- missing : self . missing ,
276
+ flags : Flags :: from_missing ( self . flags . extract_missing ( ) ) ,
266
277
components : f ( x, y, z, a) ,
267
278
}
268
279
. zero_missing_components ( )
@@ -320,7 +331,7 @@ impl Interpolator {
320
331
let components = add_alpha ( opaque, alpha) ;
321
332
DynamicColor {
322
333
cs : self . cs ,
323
- missing : self . missing ,
334
+ flags : Flags :: from_missing ( self . missing ) ,
324
335
components,
325
336
}
326
337
}
0 commit comments