@@ -131,6 +131,131 @@ fn test_path_element() {
131131 . expect ( "Drawing Failure" ) ;
132132}
133133
134+ /// An element of a series of connected lines in dash style.
135+ ///
136+ /// It's similar to [`PathElement`] but has a dash style.
137+ pub struct DashedPathElement < I : Iterator + Clone , Size : SizeDesc > {
138+ points : I ,
139+ size : Size ,
140+ spacing : Size ,
141+ style : ShapeStyle ,
142+ }
143+
144+ impl < I : Iterator + Clone , Size : SizeDesc > DashedPathElement < I , Size > {
145+ /// Create a new path
146+ /// - `points`: The iterator of the points
147+ /// - `size`: The dash size
148+ /// - `spacing`: The dash-to-dash spacing (gap size)
149+ /// - `style`: The shape style
150+ /// - returns the created element
151+ pub fn new < I0 , S > ( points : I0 , size : Size , spacing : Size , style : S ) -> Self
152+ where
153+ I0 : IntoIterator < IntoIter = I > ,
154+ S : Into < ShapeStyle > ,
155+ {
156+ Self {
157+ points : points. into_iter ( ) ,
158+ size,
159+ spacing,
160+ style : style. into ( ) ,
161+ }
162+ }
163+ }
164+
165+ impl < ' a , I : Iterator + Clone , Size : SizeDesc > PointCollection < ' a , I :: Item >
166+ for & ' a DashedPathElement < I , Size >
167+ {
168+ type Point = I :: Item ;
169+ type IntoIter = I ;
170+ fn point_iter ( self ) -> Self :: IntoIter {
171+ self . points . clone ( )
172+ }
173+ }
174+
175+ impl < I0 : Iterator + Clone , Size : SizeDesc , DB : DrawingBackend > Drawable < DB >
176+ for DashedPathElement < I0 , Size >
177+ {
178+ fn draw < I : Iterator < Item = BackendCoord > > (
179+ & self ,
180+ mut points : I ,
181+ backend : & mut DB ,
182+ ps : ( u32 , u32 ) ,
183+ ) -> Result < ( ) , DrawingErrorKind < DB :: ErrorType > > {
184+ let to_i = |( x, y) : ( f32 , f32 ) | ( x. round ( ) as i32 , y. round ( ) as i32 ) ;
185+ let to_f = |( x, y) : ( i32 , i32 ) | ( x as f32 , y as f32 ) ;
186+ let mut start = match points. next ( ) {
187+ Some ( c) => to_f ( c) ,
188+ None => return Ok ( ( ) ) ,
189+ } ;
190+ let size = self . size . in_pixels ( & ps) . max ( 0 ) as f32 ;
191+ let spacing = self . spacing . in_pixels ( & ps) . max ( 0 ) as f32 ;
192+ let mut dist = 0. ;
193+ let mut is_solid = true ;
194+ let mut queue = vec ! [ to_i( start) ] ;
195+ for curr in points {
196+ let curr_f = to_f ( curr) ;
197+ let ( dx, dy) = ( curr_f. 0 - start. 0 , curr_f. 1 - start. 1 ) ;
198+ let d = dx. hypot ( dy) . max ( f32:: EPSILON ) ;
199+ dist += d;
200+ if is_solid {
201+ if dist < size {
202+ queue. push ( curr) ;
203+ start = curr_f;
204+ } else {
205+ let t = ( dist - size) / d;
206+ start = ( start. 0 + dx * t, start. 1 + dy * t) ;
207+ queue. push ( to_i ( start) ) ;
208+ backend. draw_path ( queue. drain ( ..) , & self . style ) ?;
209+ dist = 0. ;
210+ is_solid = false ;
211+ }
212+ } else if dist < spacing {
213+ start = curr_f;
214+ } else {
215+ let t = ( dist - spacing) / d;
216+ start = ( start. 0 + dx * t, start. 1 + dy * t) ;
217+ queue. push ( to_i ( start) ) ;
218+ dist = 0. ;
219+ is_solid = true ;
220+ }
221+ }
222+ if queue. len ( ) > 1 {
223+ backend. draw_path ( queue, & self . style ) ?;
224+ }
225+ Ok ( ( ) )
226+ }
227+ }
228+
229+ #[ cfg( test) ]
230+ #[ test]
231+ fn test_dashed_path_element ( ) {
232+ use crate :: prelude:: * ;
233+ let check_list = std:: cell:: RefCell :: new ( vec ! [
234+ vec![ ( 100 , 100 ) , ( 100 , 103 ) , ( 100 , 118 ) ] ,
235+ vec![ ( 100 , 105 ) , ( 100 , 110 ) ] ,
236+ vec![ ( 100 , 112 ) , ( 100 , 117 ) ] ,
237+ vec![ ( 100 , 119 ) , ( 100 , 120 ) ] ,
238+ ] ) ;
239+ let da = crate :: create_mocked_drawing_area ( 300 , 300 , |m| {
240+ m. check_draw_path ( move |c, s, path| {
241+ assert_eq ! ( c, BLUE . to_rgba( ) ) ;
242+ assert_eq ! ( s, 7 ) ;
243+ assert_eq ! ( path, check_list. borrow_mut( ) . remove( 0 ) ) ;
244+ } ) ;
245+ m. drop_check ( |b| {
246+ assert_eq ! ( b. num_draw_path_call, 1 ) ;
247+ assert_eq ! ( b. draw_count, 1 ) ;
248+ } ) ;
249+ } ) ;
250+ da. draw ( & DashedPathElement :: new (
251+ vec ! [ ( 100 , 100 ) , ( 100 , 103 ) , ( 100 , 120 ) ] ,
252+ 5. ,
253+ 2. ,
254+ BLUE . stroke_width ( 7 ) ,
255+ ) )
256+ . expect ( "Drawing Failure" ) ;
257+ }
258+
134259/// A rectangle element
135260pub struct Rectangle < Coord > {
136261 points : [ Coord ; 2 ] ,
0 commit comments