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
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
use crate::prelude::*;
use crate::{scalar, Matrix, Path, Point, Vector};
use skia_bindings as sb;
use skia_bindings::SkPathMeasure;

pub type PathMeasure = Handle<SkPathMeasure>;

impl NativeDrop for SkPathMeasure {
    fn drop(&mut self) {
        unsafe { sb::C_SkPathMeasure_destruct(self) }
    }
}

bitflags! {
    pub struct MatrixFlags : u32 {
        const GET_POSITION = sb::SkPathMeasure_MatrixFlags_kGetPosition_MatrixFlag as _;
        const GET_TANGENT = sb::SkPathMeasure_MatrixFlags_kGetTangent_MatrixFlag as _;
        const GET_POS_AND_TAN = Self::GET_POSITION.bits | Self::GET_TANGENT.bits;
    }
}

impl Default for MatrixFlags {
    fn default() -> Self {
        Self::GET_POS_AND_TAN
    }
}

impl Default for Handle<SkPathMeasure> {
    fn default() -> Self {
        Self::from_native(unsafe { SkPathMeasure::new() })
    }
}

impl Handle<SkPathMeasure> {
    // Canonical new:
    pub fn new(path: &Path, force_closed: bool, res_scale: impl Into<Option<scalar>>) -> Self {
        Self::from_path(path, force_closed, res_scale)
    }

    // TODO: rename for_path / of_path?
    // TODO: deprecate in favor of new()?
    pub fn from_path(
        path: &Path,
        force_closed: bool,
        res_scale: impl Into<Option<scalar>>,
    ) -> Self {
        Self::from_native(unsafe {
            SkPathMeasure::new1(path.native(), force_closed, res_scale.into().unwrap_or(1.0))
        })
    }

    pub fn set_path(&mut self, path: &Path, force_closed: bool) -> &mut Self {
        unsafe { self.native_mut().setPath(path.native(), force_closed) }
        self
    }

    // TODO: why is getLength() non-const.
    pub fn length(&mut self) -> scalar {
        unsafe { self.native_mut().getLength() }
    }

    // TODO: why is getPosTan() non-const?
    // TODO: rename to get_pos_tan(), because the function has arguments?
    pub fn pos_tan(&mut self, distance: scalar) -> Option<(Point, Vector)> {
        let mut position = Point::default();
        let mut tangent = Vector::default();
        unsafe {
            self.native_mut()
                .getPosTan(distance, position.native_mut(), tangent.native_mut())
        }
        .if_true_some((position, tangent))
    }

    // TODO: why is getMatrix() non-const?
    // TODO: rename to get_matrix(), because the function has arguments?
    pub fn matrix(
        &mut self,
        distance: scalar,
        flags: impl Into<Option<MatrixFlags>>,
    ) -> Option<Matrix> {
        let mut m = Matrix::default();
        unsafe {
            self.native_mut().getMatrix(
                distance,
                m.native_mut(),
                // note: depending on the OS, different representation types are generated for MatrixFlags
                flags.into().unwrap_or_default().bits().try_into().unwrap(),
            )
        }
        .if_true_some(m)
    }

    // TODO: why is getSegment() non-const?
    // TODO: rename to get_segment(), because the function has arguments?
    pub fn segment(
        &mut self,
        start_d: scalar,
        stop_d: scalar,
        start_with_move_to: bool,
    ) -> Option<Path> {
        let mut p = Path::default();
        unsafe {
            self.native_mut()
                .getSegment(start_d, stop_d, p.native_mut(), start_with_move_to)
        }
        .if_true_some(p)
    }

    // TODO: why is isClosed() non-const?
    #[allow(clippy::wrong_self_convention)]
    pub fn is_closed(&mut self) -> bool {
        unsafe { self.native_mut().isClosed() }
    }

    // TODO: rename to has_next_contour()?
    pub fn next_contour(&mut self) -> bool {
        unsafe { self.native_mut().nextContour() }
    }
}