1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#[derive(Copy, Clone, PartialEq)]
pub struct DrawOptions {
    pub fill_color: Option<(u8, u8, u8)>,
    pub stroke_color: Option<(u8, u8, u8)>,
    pub stroke_size: f64,
}

impl DrawOptions {
    pub fn default() -> DrawOptions {
        DrawOptions {
            fill_color: None,
            stroke_color: Some((0, 0, 0)),
            stroke_size: 2.0,
        }
    }

    pub fn stroked((r, g, b): (u8, u8, u8), size: f64) -> DrawOptions {
        DrawOptions {
            fill_color: None,
            stroke_color: Some((r, g, b)),
            stroke_size: size,
        }
    }

    pub fn filled((r, g, b): (u8, u8, u8)) -> DrawOptions {
        DrawOptions {
            fill_color: Some((r, g, b)),
            stroke_color: None,
            stroke_size: 0.0,
        }
    }
}

pub enum Command {
    StartShape(DrawOptions),
    MoveTo {
        x: f64,
        y: f64,
    },
    LineTo {
        x: f64,
        y: f64,
    },
    CubicCurveTo {
        // Control Point 1
        cx1: f64,
        cy1: f64,
        // Control Point 2
        cx2: f64,
        cy2: f64,
        // End Point
        x: f64,
        y: f64,
    },
    QuadraticCurveTo {
        // Control Point
        cx: f64,
        cy: f64,
        // End Point
        x: f64,
        y: f64,
    },
    // https://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes
    ArcTo {
        // Radius of of Elipse
        rx: f64,
        ry: f64,
        // x axis rotation
        rotation: f64,
        // Which path to use
        large_arc: bool,
        sweep: bool,
        // End Point
        x: f64,
        y: f64,
    },
    CloseShape,
    EndShape,
}

pub trait DrawBackend {
    type Error;

    fn apply(&mut self, command: Command) -> Result<(), Self::Error>;
    fn apply_all<I: Iterator<Item = Command>>(&mut self, commands: I) -> Result<(), Self::Error> {
        for command in commands {
            self.apply(command)?;
        }
        Ok(())
    }
    fn close(self) -> Result<(), Self::Error>;
}