1use crate::{
2 interop,
3 prelude::{IfBoolSome, NativeAccess},
4 Path,
5};
6use skia_bindings as sb;
7use std::ffi::CString;
8
9pub 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
15pub use skia_bindings::SkParsePath_PathEncoding as PathEncoding;
16variant_name!(PathEncoding::Absolute);
17
18impl 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
32pub fn to_svg(path: &Path) -> String {
33 to_svg_with_encoding(path, encoding:PathEncoding::Absolute)
34}
35
36pub 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)]
45mod 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