1use super::geometry::{Point, Transform};
4use super::mask::Mask;
5use super::path_data::PathData;
6use super::scratch::Scratch;
7use super::style::{Fill, Style};
8
9use core::cell::RefCell;
10
11pub struct HitTest<'a, 's, D> {
13 data: D,
14 style: Style<'a>,
15 transform: Option<Transform>,
16 threshold: u8,
17 scratch: RefCell<Option<&'s mut Scratch>>,
18}
19
20impl<'a, 's, D> HitTest<'a, 's, D>
21where
22 D: PathData,
23{
24 pub fn new(data: D) -> Self {
26 Self {
27 data,
28 style: Style::Fill(Fill::NonZero),
29 transform: None,
30 threshold: 0,
31 scratch: RefCell::new(None),
32 }
33 }
34
35 pub fn with_scratch(data: D, scratch: &'s mut Scratch) -> Self {
37 Self {
38 data,
39 style: Style::Fill(Fill::NonZero),
40 transform: None,
41 threshold: 0,
42 scratch: RefCell::new(Some(scratch)),
43 }
44 }
45
46 pub fn style(&mut self, style: impl Into<Style<'a>>) -> &mut Self {
48 self.style = style.into();
49 self
50 }
51
52 pub fn transform(&mut self, transform: Option<Transform>) -> &mut Self {
54 self.transform = transform;
55 self
56 }
57
58 pub fn threshold(&mut self, threshold: u8) -> &mut Self {
60 self.threshold = threshold;
61 self
62 }
63
64 pub fn test(&self, point: impl Into<Point>) -> bool {
66 let mut scratch = self.scratch.borrow_mut();
67 let mut buf = [0u8; 1];
68 let p = point.into() * -1.;
69 if let Some(scratch) = scratch.as_mut() {
70 Mask::with_scratch(&self.data, scratch)
71 .style(self.style)
72 .offset(p)
73 .transform(self.transform)
74 .size(1, 1)
75 .render_into(&mut buf, None);
76 } else {
77 Mask::new(&self.data)
78 .style(self.style)
79 .offset(p)
80 .transform(self.transform)
81 .size(1, 1)
82 .render_into(&mut buf, None);
83 }
84 if self.threshold == 0xFF {
85 buf[0] >= self.threshold
86 } else {
87 buf[0] > self.threshold
88 }
89 }
90}