(
&self,
point: Point,
filter: &impl Fn(&Node) -> FilterResult,
)
| 325 | } |
| 326 | |
| 327 | pub(crate) fn hit_test( |
| 328 | &self, |
| 329 | point: Point, |
| 330 | filter: &impl Fn(&Node) -> FilterResult, |
| 331 | ) -> Option<(Node<'a>, Point)> { |
| 332 | // A node's `Test` frame is pushed before its children, then children in |
| 333 | // forward order, so that children are searched last-to-first and the |
| 334 | // node's own bounds are tested only after all descendants miss. |
| 335 | enum Frame<'n> { |
| 336 | Visit(Node<'n>, Point), |
| 337 | Test(Node<'n>, Point), |
| 338 | } |
| 339 | |
| 340 | let mut stack = Vec::with_capacity(self.children().len() + 1); |
| 341 | stack.push(Frame::Visit(*self, point)); |
| 342 | while let Some(frame) = stack.pop() { |
| 343 | match frame { |
| 344 | Frame::Test(node, point) => { |
| 345 | if let Some(rect) = &node.raw_bounds() { |
| 346 | if rect.contains(point) { |
| 347 | return Some((node, point)); |
| 348 | } |
| 349 | } |
| 350 | } |
| 351 | Frame::Visit(node, point) => { |
| 352 | let filter_result = filter(&node); |
| 353 | if filter_result == FilterResult::ExcludeSubtree { |
| 354 | continue; |
| 355 | } |
| 356 | if filter_result == FilterResult::Include { |
| 357 | stack.push(Frame::Test(node, point)); |
| 358 | } |
| 359 | for child in node.children() { |
| 360 | let child_point = child.direct_transform().inverse() * point; |
| 361 | stack.push(Frame::Visit(child, child_point)); |
| 362 | } |
| 363 | } |
| 364 | } |
| 365 | } |
| 366 | |
| 367 | None |
| 368 | } |
| 369 | |
| 370 | /// Returns the deepest filtered node, either this node or a descendant, |
| 371 | /// at the given point in this node's coordinate space. |
no test coverage detected