11//! Colors and color spaces.
22
3+ use core:: ops:: {
4+ Add , AddAssign , Div , DivAssign , Index , Mul , MulAssign , Neg , Sub , SubAssign ,
5+ } ;
36use core:: {
47 array,
58 fmt:: { self , Debug , Formatter } ,
69 marker:: PhantomData ,
7- ops:: Index ,
810} ;
911
10- use crate :: math :: { Affine , Linear , Vector , float :: f32 , vary:: ZDiv } ;
12+ use super :: { Affine , Linear , Vector , vary:: ZDiv } ;
1113
1214//
1315// Types
@@ -195,6 +197,7 @@ impl Color3f<Rgb> {
195197 #[ cfg( feature = "fp" ) ]
196198 #[ inline]
197199 pub fn to_linear ( self ) -> Color3f < LinRgb > {
200+ use super :: float:: f32;
198201 self . 0 . map ( |c| f32:: powf ( c, GAMMA ) ) . into ( )
199202 }
200203
@@ -209,7 +212,7 @@ impl Color3f<Rgb> {
209212 let h = if d == 0.0 {
210213 0.0
211214 } else if max == r {
212- f32:: rem_euclid ( ( g - b) / d, 6.0 )
215+ super :: float :: f32:: rem_euclid ( ( g - b) / d, 6.0 )
213216 } else if max == g {
214217 ( b - r) / d + 2.0
215218 } else {
@@ -277,6 +280,7 @@ impl Color3f<LinRgb> {
277280 #[ cfg( feature = "fp" ) ]
278281 #[ inline]
279282 pub fn to_srgb ( self ) -> Color3f < Rgb > {
283+ use super :: float:: f32;
280284 self . 0 . map ( |c| f32:: powf ( c, INV_GAMMA ) ) . into ( )
281285 }
282286}
@@ -525,12 +529,102 @@ impl<R, Sp> From<R> for Color<R, Sp> {
525529 }
526530}
527531
532+ //
533+ // Arithmetic trait impls
534+ //
535+
536+ //
537+ // Arithmetic traits
538+ //
539+
540+ /// The color += color operator.
541+ impl < R , D , Sp > AddAssign < D > for Color < R , Sp >
542+ where
543+ Self : Affine < Diff = D > ,
544+ {
545+ #[ inline]
546+ fn add_assign ( & mut self , rhs : D ) {
547+ * self = Affine :: add ( & * self , & rhs) ;
548+ }
549+ }
550+
551+ /// The color -= color operator.
552+ impl < R , D , Sp > SubAssign < D > for Color < R , Sp >
553+ where
554+ D : Linear ,
555+ Self : Affine < Diff = D > ,
556+ {
557+ #[ inline]
558+ fn sub_assign ( & mut self , rhs : D ) {
559+ * self += rhs. neg ( ) ;
560+ }
561+ }
562+
563+ // The color *= scalar operator.
564+ impl < R , Sc , Sp > MulAssign < Sc > for Color < R , Sp >
565+ where
566+ Self : Linear < Scalar = Sc > ,
567+ {
568+ #[ inline]
569+ fn mul_assign ( & mut self , rhs : Sc ) {
570+ * self = Linear :: mul ( & * self , rhs) ;
571+ }
572+ }
573+
574+ // The color /= scalar operator.
575+ impl < R , Sp > DivAssign < f32 > for Color < R , Sp >
576+ where
577+ Self : Linear < Scalar = f32 > ,
578+ {
579+ #[ inline]
580+ fn div_assign ( & mut self , rhs : f32 ) {
581+ use crate :: math:: ApproxEq ;
582+ debug_assert ! ( !rhs. approx_eq( & 0.0 ) ) ;
583+ * self = Linear :: mul ( & * self , rhs. recip ( ) ) ;
584+ }
585+ }
586+
587+ /// The color negation operator.
588+ impl < R , Sp > Neg for Color < R , Sp >
589+ where
590+ Self : Linear ,
591+ {
592+ type Output = Self ;
593+
594+ #[ inline]
595+ fn neg ( self ) -> Self {
596+ <Self as Linear >:: neg ( & self )
597+ }
598+ }
599+
600+ /// The scalar * color operator.
601+ impl < R , Sp > Mul < Color < R , Sp > > for <Color < R , Sp > as Linear >:: Scalar
602+ where
603+ Color < R , Sp > : Linear ,
604+ {
605+ type Output = Color < R , Sp > ;
606+
607+ #[ inline]
608+ fn mul ( self , rhs : Color < R , Sp > ) -> Color < R , Sp > {
609+ rhs * self
610+ }
611+ }
612+
613+ // The color + color operator.
614+ impl_op ! ( Add :: add, Color , <Self as Affine >:: Diff , +=, bound=Affine ) ;
615+ // The color - color operator.
616+ impl_op ! ( Sub :: sub, Color , <Self as Affine >:: Diff , -=, bound=Affine ) ;
617+ // The color * scalar operator.
618+ impl_op ! ( Mul :: mul, Color , <Self as Linear >:: Scalar , *=) ;
619+ // The color / scalar operator.
620+ impl_op ! ( Div :: div, Color , f32 , /=, bound=Linear <Scalar = f32 >) ;
621+
528622#[ cfg( test) ]
529623mod tests {
530624 use super :: * ;
531625
532626 #[ test]
533- fn color_components ( ) {
627+ fn rgb_components ( ) {
534628 assert_eq ! ( rgb( 0xFF , 0 , 0 ) . r( ) , 0xFF ) ;
535629 assert_eq ! ( rgb( 0 , 0xFF , 0 ) . g( ) , 0xFF ) ;
536630 assert_eq ! ( rgb( 0 , 0 , 0xFF ) . b( ) , 0xFF ) ;
@@ -541,6 +635,40 @@ mod tests {
541635 assert_eq ! ( rgba( 0 , 0 , 0 , 0xFF ) . a( ) , 0xFF ) ;
542636 }
543637
638+ #[ test]
639+ fn hsl_components ( ) {
640+ assert_eq ! ( hsl( 0xFF , 0 , 0 ) . h( ) , 0xFF ) ;
641+ assert_eq ! ( hsl( 0 , 0xFF , 0 ) . s( ) , 0xFF ) ;
642+ assert_eq ! ( hsl( 0 , 0 , 0xFF ) . l( ) , 0xFF ) ;
643+
644+ assert_eq ! ( hsla( 0xFF , 0 , 0 , 0 ) . h( ) , 0xFF ) ;
645+ assert_eq ! ( hsla( 0 , 0xFF , 0 , 0 ) . s( ) , 0xFF ) ;
646+ assert_eq ! ( hsla( 0 , 0 , 0xFF , 0 ) . l( ) , 0xFF ) ;
647+ assert_eq ! ( hsla( 0 , 0 , 0 , 0xFF ) . a( ) , 0xFF ) ;
648+ }
649+
650+ #[ test]
651+ fn rgb_f32_ops ( ) {
652+ let lhs = rgb ( 0.5 , 0.625 , 0.75 ) ;
653+ let rhs = rgb ( 0.125 , 0.25 , 0.375 ) ;
654+
655+ assert_eq ! ( lhs + rhs, rgb( 0.625 , 0.875 , 1.125 ) ) ;
656+ assert_eq ! ( lhs - rhs, rgb( 0.375 , 0.375 , 0.375 ) ) ;
657+ assert_eq ! ( lhs * 0.5 , rgb( 0.25 , 0.3125 , 0.375 ) ) ;
658+ assert_eq ! ( 0.5 * lhs, rgb( 0.25 , 0.3125 , 0.375 ) ) ;
659+ assert_eq ! ( lhs / 2.0 , rgb( 0.25 , 0.3125 , 0.375 ) ) ;
660+ assert_eq ! ( -lhs, rgb( -0.5 , -0.625 , -0.75 ) ) ;
661+ }
662+
663+ #[ test]
664+ fn rgb_u8_ops ( ) {
665+ let lhs = rgb ( 0x77 , 0x88 , 0x99 ) ;
666+ let rhs = [ 0x11_i32 , 0x33 , 0x55 ] . into ( ) ;
667+
668+ assert_eq ! ( lhs + rhs, rgb( 0x88 , 0xBB , 0xEE ) ) ;
669+ assert_eq ! ( lhs - rhs, rgb( 0x66 , 0x55 , 0x44 ) ) ;
670+ }
671+
544672 #[ test]
545673 fn rgb_to_hsl ( ) {
546674 let cases = [
0 commit comments