pathfinder_path_utils/
orientation.rs

1// pathfinder/path-utils/src/orientation.rs
2//
3// Copyright © 2018 The Pathfinder Project Developers.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
11use euclid::Point2D;
12use lyon_path::PathEvent;
13
14#[derive(Clone, Copy, Debug, PartialEq)]
15pub enum Orientation {
16    Ccw = -1,
17    Cw = 1,
18}
19
20impl Orientation {
21    /// This follows the FreeType algorithm.
22    pub fn from_path<I>(stream: I) -> Orientation where I: Iterator<Item = PathEvent> {
23        let (mut from, mut subpath_start) = (Point2D::zero(), Point2D::zero());
24        let mut area = 0.0;
25        for event in stream {
26            match event {
27                PathEvent::MoveTo(to) => {
28                    from = to;
29                    subpath_start = to;
30                }
31                PathEvent::LineTo(to) => {
32                    area += det(&from, &to);
33                    from = to;
34                }
35                PathEvent::QuadraticTo(ctrl, to) => {
36                    area += det(&from, &ctrl) + det(&ctrl, &to);
37                    from = to;
38                }
39                PathEvent::CubicTo(ctrl0, ctrl1, to) => {
40                    area += det(&from, &ctrl0) + det(&ctrl0, &ctrl1) + det(&ctrl1, &to);
41                    from = to;
42                }
43                PathEvent::Arc(..) => {
44                    // TODO(pcwalton)
45                }
46                PathEvent::Close => {
47                    area += det(&from, &subpath_start);
48                    from = subpath_start;
49                }
50            }
51        }
52        if area <= 0.0 {
53            Orientation::Ccw
54        } else {
55            Orientation::Cw
56        }
57    }
58}
59
60fn det(a: &Point2D<f32>, b: &Point2D<f32>) -> f32 {
61    a.x * b.y - a.y * b.x
62}