1 | use crate::{ |
2 | interop, |
3 | prelude::{IfBoolSome, NativeAccess}, |
4 | Path, |
5 | }; |
6 | use skia_bindings as sb; |
7 | use std::ffi::CString; |
8 | |
9 | pub fn from_svg(svg: impl AsRef<str>) -> Option<Path> { |
10 | let str: CString = CString::new(svg.as_ref()).unwrap(); |
11 | let mut path: Handle = Path::default(); |
12 | unsafe { sb::SkParsePath_FromSVGString(str_:str.as_ptr(), arg1:path.native_mut()) }.if_true_some(path) |
13 | } |
14 | |
15 | pub use skia_bindings::SkParsePath_PathEncoding as PathEncoding; |
16 | variant_name!(PathEncoding::Absolute); |
17 | |
18 | impl Path { |
19 | pub fn from_svg(svg: impl AsRef<str>) -> Option<Path> { |
20 | from_svg(svg) |
21 | } |
22 | |
23 | pub fn to_svg(&self) -> String { |
24 | to_svg(self) |
25 | } |
26 | |
27 | pub fn to_svg_with_encoding(&self, encoding: PathEncoding) -> String { |
28 | to_svg_with_encoding(self, encoding) |
29 | } |
30 | } |
31 | |
32 | pub fn to_svg(path: &Path) -> String { |
33 | to_svg_with_encoding(path, encoding:PathEncoding::Absolute) |
34 | } |
35 | |
36 | pub fn to_svg_with_encoding(path: &Path, encoding: PathEncoding) -> String { |
37 | interop&str::String::construct(|svg: *mut SkString| { |
38 | unsafe { sb::C_SkParsePath_ToSVGString(self_:path.native(), uninitialized:svg, encoding) }; |
39 | }) |
40 | .as_str() |
41 | .into() |
42 | } |
43 | |
44 | #[cfg (test)] |
45 | mod tests { |
46 | use super::Path; |
47 | |
48 | #[test ] |
49 | fn simple_path_to_svg_and_back() { |
50 | let mut path = Path::default(); |
51 | path.move_to((0, 0)); |
52 | path.line_to((100, 100)); |
53 | path.line_to((0, 100)); |
54 | path.close(); |
55 | |
56 | let svg = Path::to_svg(&path); |
57 | assert_eq!(svg, "M0 0L100 100L0 100L0 0Z" ); |
58 | // And back. Someone may find why they are not equal. |
59 | let _recreated = Path::from_svg(svg).expect("Failed to parse SVG path" ); |
60 | } |
61 | } |
62 | |