8
8
#include < cmath>
9
9
#include < sstream>
10
10
11
+ #include " impeller/geometry/constants.h"
11
12
#include " impeller/geometry/scalar.h"
12
13
#include " impeller/geometry/vector.h"
13
14
@@ -127,11 +128,65 @@ Color::Color(const ColorHSB& hsbColor) : Color(hsbColor.ToRGBA()) {}
127
128
Color::Color (const Vector4& value)
128
129
: red(value.x), green(value.y), blue(value.z), alpha(value.w) {}
129
130
130
- Color Min (Color c, float threshold) {
131
+ static constexpr Color Min (Color c, float threshold) {
131
132
return Color (std::min (c.red , threshold), std::min (c.green , threshold),
132
133
std::min (c.blue , threshold), std::min (c.alpha , threshold));
133
134
}
134
135
136
+ // The following HSV utilities correspond to the W3C blend definitions
137
+ // implemented in: impeller/compiler/shader_lib/impeller/blending.glsl
138
+
139
+ static constexpr Scalar Luminosity (Vector3 color) {
140
+ return color.x * 0.3 + color.y * 0.59 + color.z * 0.11 ;
141
+ }
142
+
143
+ static constexpr Vector3 ClipColor (Vector3 color) {
144
+ Scalar lum = Luminosity (color);
145
+ Scalar mn = std::min (std::min (color.x , color.y ), color.z );
146
+ Scalar mx = std::max (std::max (color.x , color.y ), color.z );
147
+ if (mn < 0.0 ) {
148
+ color = lum + (((color - lum) * lum) / (lum - mn + kEhCloseEnough ));
149
+ }
150
+ if (mx > 1.0 ) {
151
+ color = lum + (((color - lum) * (1.0 - lum)) / (mx - lum + kEhCloseEnough ));
152
+ }
153
+ return Vector3 ();
154
+ }
155
+
156
+ static constexpr Vector3 SetLuminosity (Vector3 color, Scalar luminosity) {
157
+ Scalar relative_lum = luminosity - Luminosity (color);
158
+ return ClipColor (color + relative_lum);
159
+ }
160
+
161
+ static constexpr Scalar Saturation (Vector3 color) {
162
+ return std::max (std::max (color.x , color.y ), color.z ) -
163
+ std::min (std::min (color.x , color.y ), color.z );
164
+ }
165
+
166
+ static constexpr Vector3 SetSaturation (Vector3 color, Scalar saturation) {
167
+ Scalar mn = std::min (std::min (color.x , color.y ), color.z );
168
+ Scalar mx = std::max (std::max (color.x , color.y ), color.z );
169
+ return (mn < mx) ? ((color - mn) * saturation) / (mx - mn) : Vector3 ();
170
+ }
171
+
172
+ static constexpr Vector3 ComponentChoose (Vector3 a,
173
+ Vector3 b,
174
+ Vector3 value,
175
+ Scalar cutoff) {
176
+ return Vector3 (value.x > cutoff ? b.x : a.x , //
177
+ value.y > cutoff ? b.y : a.y , //
178
+ value.z > cutoff ? b.z : a.z //
179
+ );
180
+ }
181
+
182
+ static constexpr Vector3 ToRGB (Color color) {
183
+ return {color.red , color.green , color.blue };
184
+ }
185
+
186
+ static constexpr Color FromRGB (Vector3 color, Scalar alpha) {
187
+ return {color.x , color.y , color.z , alpha};
188
+ }
189
+
135
190
Color Color::BlendColor (const Color& src,
136
191
const Color& dst,
137
192
BlendMode blend_mode) {
@@ -237,6 +292,24 @@ Color Color::BlendColor(const Color& src,
237
292
// s.a * d.a - 2 * (d.a - d) * (s.a - s)
238
293
return src.alpha * dst.alpha - 2 * (dst.alpha - d) * (src.alpha - s);
239
294
});
295
+ case BlendMode::kSoftLight : {
296
+ Vector3 dst_rgb = ToRGB (dst);
297
+ Vector3 src_rgb = ToRGB (src);
298
+ Vector3 d = ComponentChoose (
299
+ ((16.0 * dst_rgb - 12.0 ) * dst_rgb + 4.0 ) * dst_rgb, //
300
+ Vector3 (std::sqrt (dst_rgb.x ), std::sqrt (dst_rgb.y ),
301
+ std::sqrt (dst_rgb.z )), //
302
+ dst_rgb, //
303
+ 0.25 );
304
+ Color blended =
305
+ FromRGB (ComponentChoose (
306
+ dst_rgb - (1.0 - 2.0 * src) * dst * (1.0 - dst_rgb), //
307
+ dst_rgb + (2.0 * src_rgb - 1.0 ) * (d - dst_rgb), //
308
+ src_rgb, //
309
+ 0.5 ),
310
+ dst.alpha );
311
+ return blended + dst * (1 - blended.alpha );
312
+ }
240
313
case BlendMode::kDifference :
241
314
return apply_rgb_srcover_alpha ([&](auto s, auto d) {
242
315
// s + d - 2 * min(s * d.a, d * s.a);
@@ -252,13 +325,38 @@ Color Color::BlendColor(const Color& src,
252
325
// s * (1 - d.a) + d * (1 - s.a) + (s * d)
253
326
return s * (1 - dst.alpha ) + d * (1 - src.alpha ) + (s * d);
254
327
});
255
- case BlendMode::kHue :
256
- case BlendMode::kSaturation :
257
- case BlendMode::kColor :
258
- case BlendMode::kLuminosity :
259
- case BlendMode::kSoftLight :
260
- default :
261
- return src + dst * (1 - src.alpha );
328
+ case BlendMode::kHue : {
329
+ Vector3 dst_rgb = ToRGB (dst);
330
+ Vector3 src_rgb = ToRGB (src);
331
+ Color blended =
332
+ FromRGB (SetLuminosity (SetSaturation (src_rgb, Saturation (dst_rgb)),
333
+ Luminosity (dst_rgb)),
334
+ dst.alpha );
335
+ return blended + dst * (1 - blended.alpha );
336
+ }
337
+ case BlendMode::kSaturation : {
338
+ Vector3 dst_rgb = ToRGB (dst);
339
+ Vector3 src_rgb = ToRGB (src);
340
+ Color blended =
341
+ FromRGB (SetLuminosity (SetSaturation (dst_rgb, Saturation (src_rgb)),
342
+ Luminosity (dst_rgb)),
343
+ dst.alpha );
344
+ return blended + dst * (1 - blended.alpha );
345
+ }
346
+ case BlendMode::kColor : {
347
+ Vector3 dst_rgb = ToRGB (dst);
348
+ Vector3 src_rgb = ToRGB (src);
349
+ Color blended =
350
+ FromRGB (SetLuminosity (src_rgb, Luminosity (dst_rgb)), dst.alpha );
351
+ return blended + dst * (1 - blended.alpha );
352
+ }
353
+ case BlendMode::kLuminosity : {
354
+ Vector3 dst_rgb = ToRGB (dst);
355
+ Vector3 src_rgb = ToRGB (src);
356
+ Color blended =
357
+ FromRGB (SetLuminosity (dst_rgb, Luminosity (src_rgb)), dst.alpha );
358
+ return blended + dst * (1 - blended.alpha );
359
+ }
262
360
}
263
361
}
264
362
0 commit comments