44//!
55//! [`Gradient`]: crate::core::Gradient;
66use crate :: core:: gradient:: ColorStop ;
7- use crate :: core:: { Color , Point } ;
7+ use crate :: core:: { self , Color , Point , Rectangle } ;
88use std:: cmp:: Ordering ;
99
1010#[ derive( Debug , Clone , PartialEq ) ]
@@ -23,6 +23,15 @@ impl From<Linear> for Gradient {
2323 }
2424}
2525
26+ impl Gradient {
27+ /// Packs the [`Gradient`] for use in shader code.
28+ pub fn pack ( & self ) -> Packed {
29+ match self {
30+ Gradient :: Linear ( linear) => linear. pack ( ) ,
31+ }
32+ }
33+ }
34+
2635/// A linear gradient that can be used in the style of [`Fill`] or [`Stroke`].
2736///
2837/// [`Fill`]: crate::geometry::Fill;
@@ -85,4 +94,62 @@ impl Linear {
8594
8695 self
8796 }
97+
98+ /// Packs the [`Gradient`] for use in shader code.
99+ pub fn pack ( & self ) -> Packed {
100+ let mut data: [ f32 ; 44 ] = [ 0.0 ; 44 ] ;
101+
102+ for ( index, stop) in self . stops . iter ( ) . enumerate ( ) {
103+ let [ r, g, b, a] =
104+ stop. map_or ( Color :: default ( ) , |s| s. color ) . into_linear ( ) ;
105+
106+ data[ index * 4 ] = r;
107+ data[ ( index * 4 ) + 1 ] = g;
108+ data[ ( index * 4 ) + 2 ] = b;
109+ data[ ( index * 4 ) + 3 ] = a;
110+
111+ data[ 32 + index] = stop. map_or ( 2.0 , |s| s. offset ) ;
112+ }
113+
114+ data[ 40 ] = self . start . x ;
115+ data[ 41 ] = self . start . y ;
116+ data[ 42 ] = self . end . x ;
117+ data[ 43 ] = self . end . y ;
118+
119+ Packed ( data)
120+ }
121+ }
122+
123+ /// Packed [`Gradient`] data for use in shader code.
124+ #[ derive( Debug , Copy , Clone , PartialEq ) ]
125+ #[ repr( C ) ]
126+ pub struct Packed ( [ f32 ; 44 ] ) ;
127+
128+ /// Creates a new [`Packed`] gradient for use in shader code.
129+ pub fn pack ( gradient : & core:: Gradient , bounds : Rectangle ) -> Packed {
130+ match gradient {
131+ core:: Gradient :: Linear ( linear) => {
132+ let mut data: [ f32 ; 44 ] = [ 0.0 ; 44 ] ;
133+
134+ for ( index, stop) in linear. stops . iter ( ) . enumerate ( ) {
135+ let [ r, g, b, a] =
136+ stop. map_or ( Color :: default ( ) , |s| s. color ) . into_linear ( ) ;
137+
138+ data[ index * 4 ] = r;
139+ data[ ( index * 4 ) + 1 ] = g;
140+ data[ ( index * 4 ) + 2 ] = b;
141+ data[ ( index * 4 ) + 3 ] = a;
142+ data[ 32 + index] = stop. map_or ( 2.0 , |s| s. offset ) ;
143+ }
144+
145+ let ( start, end) = linear. angle . to_distance ( & bounds) ;
146+
147+ data[ 40 ] = start. x ;
148+ data[ 41 ] = start. y ;
149+ data[ 42 ] = end. x ;
150+ data[ 43 ] = end. y ;
151+
152+ Packed ( data)
153+ }
154+ }
88155}
0 commit comments