@@ -24,17 +24,23 @@ fn make_svg_opacity<C: Color>(color: &C) -> String {
2424enum Target < ' a > {
2525 File ( String , & ' a Path ) ,
2626 Buffer ( & ' a mut String ) ,
27+ // TODO: At this point we won't make the breaking change
28+ // so the u8 buffer is still supported. But in 0.3, we definitely
29+ // should get rid of this.
30+ #[ cfg( feature = "deprecated_items" ) ]
31+ U8Buffer ( String , & ' a mut Vec < u8 > ) ,
2732}
2833
2934impl Target < ' _ > {
3035 fn get_mut ( & mut self ) -> & mut String {
3136 match self {
3237 Target :: File ( ref mut buf, _) => buf,
3338 Target :: Buffer ( buf) => buf,
39+ #[ cfg( feature = "deprecated_items" ) ]
40+ Target :: U8Buffer ( ref mut buf, _) => buf,
3441 }
3542 }
3643}
37- //use svg::node::element::{Circle, Line, Polygon, Polyline, Rectangle, Text};
3844
3945enum SVGTag {
4046 SVG ,
@@ -72,6 +78,16 @@ pub struct SVGBackend<'a> {
7278}
7379
7480impl < ' a > SVGBackend < ' a > {
81+ fn escape_and_push ( buf : & mut String , value : & str ) {
82+ value. chars ( ) . for_each ( |c| match c {
83+ '<' => buf. push_str ( "<" ) ,
84+ '>' => buf. push_str ( ">" ) ,
85+ '&' => buf. push_str ( "&" ) ,
86+ '"' => buf. push_str ( """ ) ,
87+ '\'' => buf. push_str ( "'" ) ,
88+ other => buf. push ( other) ,
89+ } ) ;
90+ }
7591 fn open_tag ( & mut self , tag : SVGTag , attr : & [ ( & str , & str ) ] , close : bool ) {
7692 let buf = self . target . get_mut ( ) ;
7793 buf. push_str ( "<" ) ;
@@ -80,14 +96,14 @@ impl<'a> SVGBackend<'a> {
8096 buf. push_str ( " " ) ;
8197 buf. push_str ( key) ;
8298 buf. push_str ( "=\" " ) ;
83- buf . push_str ( value) ;
99+ Self :: escape_and_push ( buf , value) ;
84100 buf. push_str ( "\" " ) ;
85101 }
86102 if close {
87103 buf. push_str ( "/>\n " ) ;
88104 } else {
89105 self . tag_stack . push ( tag) ;
90- buf. push_str ( ">" ) ;
106+ buf. push_str ( ">\n " ) ;
91107 }
92108 }
93109
@@ -127,8 +143,26 @@ impl<'a> SVGBackend<'a> {
127143 ret
128144 }
129145
130- /// Create a new SVG drawing backend and store the document into a u8 buffer
131- pub fn with_buffer ( buf : & ' a mut String , size : ( u32 , u32 ) ) -> Self {
146+ /// Create a new SVG drawing backend and store the document into a u8 vector
147+ #[ cfg( feature = "deprecated_items" ) ]
148+ #[ deprecated(
149+ note = "This will be replaced by `with_string`, consider use `with_string` to avoid breaking change in the future"
150+ ) ]
151+ pub fn with_buffer ( buf : & ' a mut Vec < u8 > , size : ( u32 , u32 ) ) -> Self {
152+ let mut ret = Self {
153+ target : Target :: U8Buffer ( String :: default ( ) , buf) ,
154+ size,
155+ tag_stack : vec ! [ ] ,
156+ saved : false ,
157+ } ;
158+
159+ ret. init_svg_file ( size) ;
160+
161+ ret
162+ }
163+
164+ /// Create a new SVG drawing backend and store the document into a String buffer
165+ pub fn with_string ( buf : & ' a mut String , size : ( u32 , u32 ) ) -> Self {
132166 let mut ret = Self {
133167 target : Target :: Buffer ( buf) ,
134168 size,
@@ -165,6 +199,11 @@ impl<'a> DrawingBackend for SVGBackend<'a> {
165199 . map_err ( DrawingErrorKind :: DrawingError ) ?;
166200 }
167201 Target :: Buffer ( _) => { }
202+ #[ cfg( feature = "deprecated_items" ) ]
203+ Target :: U8Buffer ( ref actual, ref mut target) => {
204+ target. clear ( ) ;
205+ target. extend_from_slice ( actual. as_bytes ( ) ) ;
206+ }
168207 }
169208 self . saved = true ;
170209 }
@@ -429,7 +468,8 @@ impl<'a> DrawingBackend for SVGBackend<'a> {
429468 false ,
430469 ) ;
431470
432- self . target . get_mut ( ) . push_str ( text) ;
471+ Self :: escape_and_push ( self . target . get_mut ( ) , text) ;
472+ self . target . get_mut ( ) . push_str ( "\n " ) ;
433473
434474 self . close_tag ( ) ;
435475
@@ -554,9 +594,9 @@ mod test {
554594 }
555595
556596 fn draw_mesh_with_custom_ticks ( tick_size : i32 , test_name : & str ) {
557- let mut buffer : String = Default :: default ( ) ;
597+ let mut content : String = Default :: default ( ) ;
558598 {
559- let root = SVGBackend :: with_buffer ( & mut buffer , ( 500 , 500 ) ) . into_drawing_area ( ) ;
599+ let root = SVGBackend :: with_string ( & mut content , ( 500 , 500 ) ) . into_drawing_area ( ) ;
560600
561601 let mut chart = ChartBuilder :: on ( & root)
562602 . caption ( "This is a test" , ( "sans-serif" , 20 ) )
@@ -571,7 +611,6 @@ mod test {
571611 . unwrap ( ) ;
572612 }
573613
574- let content = buffer;
575614 checked_save_file ( test_name, & content) ;
576615
577616 assert ! ( content. contains( "This is a test" ) ) ;
@@ -589,9 +628,9 @@ mod test {
589628
590629 #[ test]
591630 fn test_text_alignments ( ) {
592- let mut buffer : String = Default :: default ( ) ;
631+ let mut content : String = Default :: default ( ) ;
593632 {
594- let mut root = SVGBackend :: with_buffer ( & mut buffer , ( 500 , 500 ) ) ;
633+ let mut root = SVGBackend :: with_string ( & mut content , ( 500 , 500 ) ) ;
595634
596635 let style = TextStyle :: from ( ( "sans-serif" , 20 ) . into_font ( ) )
597636 . pos ( Pos :: new ( HPos :: Right , VPos :: Top ) ) ;
@@ -604,7 +643,6 @@ mod test {
604643 root. draw_text ( "left-align" , & style, ( 150 , 200 ) ) . unwrap ( ) ;
605644 }
606645
607- let content = buffer;
608646 checked_save_file ( "test_text_alignments" , & content) ;
609647
610648 for svg_line in content. split ( "</text>" ) {
@@ -624,9 +662,9 @@ mod test {
624662
625663 #[ test]
626664 fn test_text_draw ( ) {
627- let mut buffer : String = Default :: default ( ) ;
665+ let mut content : String = Default :: default ( ) ;
628666 {
629- let root = SVGBackend :: with_buffer ( & mut buffer , ( 1500 , 800 ) ) . into_drawing_area ( ) ;
667+ let root = SVGBackend :: with_string ( & mut content , ( 1500 , 800 ) ) . into_drawing_area ( ) ;
630668 let root = root
631669 . titled ( "Image Title" , ( "sans-serif" , 60 ) . into_font ( ) )
632670 . unwrap ( ) ;
@@ -676,7 +714,6 @@ mod test {
676714 }
677715 }
678716
679- let content = buffer;
680717 checked_save_file ( "test_text_draw" , & content) ;
681718
682719 assert_eq ! ( content. matches( "dog" ) . count( ) , 36 ) ;
@@ -686,10 +723,10 @@ mod test {
686723
687724 #[ test]
688725 fn test_text_clipping ( ) {
689- let mut buffer : String = Default :: default ( ) ;
726+ let mut content : String = Default :: default ( ) ;
690727 {
691728 let ( width, height) = ( 500_i32 , 500_i32 ) ;
692- let root = SVGBackend :: with_buffer ( & mut buffer , ( width as u32 , height as u32 ) )
729+ let root = SVGBackend :: with_string ( & mut content , ( width as u32 , height as u32 ) )
693730 . into_drawing_area ( ) ;
694731
695732 let style = TextStyle :: from ( ( "sans-serif" , 20 ) . into_font ( ) )
@@ -711,16 +748,15 @@ mod test {
711748 . unwrap ( ) ;
712749 }
713750
714- let content = buffer;
715751 checked_save_file ( "test_text_clipping" , & content) ;
716752 }
717753
718754 #[ test]
719755 fn test_series_labels ( ) {
720- let mut buffer = String :: default ( ) ;
756+ let mut content = String :: default ( ) ;
721757 {
722758 let ( width, height) = ( 500 , 500 ) ;
723- let root = SVGBackend :: with_buffer ( & mut buffer , ( width, height) ) . into_drawing_area ( ) ;
759+ let root = SVGBackend :: with_string ( & mut content , ( width, height) ) . into_drawing_area ( ) ;
724760
725761 let mut chart = ChartBuilder :: on ( & root)
726762 . caption ( "All series label positions" , ( "sans-serif" , 20 ) )
@@ -770,16 +806,15 @@ mod test {
770806 }
771807 }
772808
773- let content = buffer;
774809 checked_save_file ( "test_series_labels" , & content) ;
775810 }
776811
777812 #[ test]
778813 fn test_draw_pixel_alphas ( ) {
779- let mut buffer = String :: default ( ) ;
814+ let mut content = String :: default ( ) ;
780815 {
781816 let ( width, height) = ( 100_i32 , 100_i32 ) ;
782- let root = SVGBackend :: with_buffer ( & mut buffer , ( width as u32 , height as u32 ) )
817+ let root = SVGBackend :: with_string ( & mut content , ( width as u32 , height as u32 ) )
783818 . into_drawing_area ( ) ;
784819 root. fill ( & WHITE ) . unwrap ( ) ;
785820
@@ -790,7 +825,6 @@ mod test {
790825 }
791826 }
792827
793- let content = buffer;
794828 checked_save_file ( "test_draw_pixel_alphas" , & content) ;
795829 }
796830}
0 commit comments