@@ -22,7 +22,12 @@ pub enum BlendMode {
2222 Overlay ,
2323 Darken ,
2424 Lighten ,
25- // TODO: Add SoftLight, HardLight, ColorDodge, ColorBurn, etc.
25+ ColorDodge ,
26+ ColorBurn ,
27+ HardLight ,
28+ SoftLight ,
29+ Difference ,
30+ Exclusion ,
2631}
2732
2833// stores sRGB under the hood, with lots of conversion funcs
@@ -637,21 +642,58 @@ impl Color {
637642 }
638643
639644 #[ inline]
640- fn blend_channel ( mode : BlendMode , s : ColorFloat , d : ColorFloat ) -> ColorFloat {
645+ fn blend_channel ( mode : BlendMode , b : ColorFloat , s : ColorFloat ) -> ColorFloat {
641646 use BlendMode :: * ;
647+
642648 match mode {
649+ // source: https://www.w3.org/TR/compositing-1/
650+ // separable blend modes
643651 Normal => s,
644- Multiply => s * d,
645- Screen => 1.0 - ( 1.0 - s) * ( 1.0 - d) ,
646- Overlay => {
647- if d <= 0.5 {
648- 2.0 * s * d
652+ Multiply => b * s,
653+ Screen => b + s - ( b * s) ,
654+ Overlay => Self :: blend_channel ( HardLight , b, s) ,
655+ Darken => b. min ( s) ,
656+ Lighten => b. max ( s) ,
657+ ColorDodge => {
658+ if b == 0.0 {
659+ 0.0
660+ } else if s == 1.0 {
661+ 1.0
662+ } else {
663+ ( 1.0 as ColorFloat ) . min ( b / ( 1.0 - s) )
664+ }
665+ }
666+ ColorBurn => {
667+ if b == 1.0 {
668+ 1.0
669+ } else if s == 0.0 {
670+ 0.0
671+ } else {
672+ 1.0 - ( 1.0 as ColorFloat ) . min ( ( 1.0 - b) / s)
673+ }
674+ }
675+ HardLight => {
676+ if s <= 0.5 {
677+ Self :: blend_channel ( Multiply , b, 2.0 * s)
678+ } else {
679+ Self :: blend_channel ( Screen , b, 2.0 * s - 1.0 )
680+ }
681+ }
682+ SoftLight => {
683+ if s <= 0.5 {
684+ b - ( 1.0 - 2.0 * s) * b * ( 1.0 - b)
649685 } else {
650- 1.0 - 2.0 * ( 1.0 - s) * ( 1.0 - d)
686+ let d = if b <= 0.25 {
687+ ( ( 16.0 * b - 12.0 ) * b + 4.0 ) * b
688+ } else {
689+ b. sqrt ( )
690+ } ;
691+ b + ( 2.0 * s - 1.0 ) * ( d - b)
651692 }
652693 }
653- Darken => s. min ( d) ,
654- Lighten => s. max ( d) ,
694+ Difference => ( b - s) . abs ( ) ,
695+ Exclusion => b + s - 2.0 * b * s,
696+ // non-separable blend modes
655697 }
656698 }
657699}
0 commit comments