| 414 | }; |
| 415 | |
| 416 | export function findBoundingRects( |
| 417 | hostRoot: Instance, |
| 418 | selectors: Array<Selector>, |
| 419 | ): Array<BoundingRect> { |
| 420 | if (!supportsTestSelectors) { |
| 421 | throw new Error(class="st">'Test selector API is not supported by this renderer.'); |
| 422 | } |
| 423 | |
| 424 | const instanceRoots = findAllNodes(hostRoot, selectors); |
| 425 | |
| 426 | const boundingRects: Array<BoundingRect> = []; |
| 427 | for (let i = 0; i < instanceRoots.length; i++) { |
| 428 | boundingRects.push(getBoundingRect(instanceRoots[i])); |
| 429 | } |
| 430 | |
| 431 | for (let i = boundingRects.length - 1; i > 0; i--) { |
| 432 | const targetRect = boundingRects[i]; |
| 433 | const targetLeft = targetRect.x; |
| 434 | const targetRight = targetLeft + targetRect.width; |
| 435 | const targetTop = targetRect.y; |
| 436 | const targetBottom = targetTop + targetRect.height; |
| 437 | |
| 438 | for (let j = i - 1; j >= 0; j--) { |
| 439 | if (i !== j) { |
| 440 | const otherRect = boundingRects[j]; |
| 441 | const otherLeft = otherRect.x; |
| 442 | const otherRight = otherLeft + otherRect.width; |
| 443 | const otherTop = otherRect.y; |
| 444 | const otherBottom = otherTop + otherRect.height; |
| 445 | |
| 446 | class="cm">// Merging all rects to the minimums set would be complicated, |
| 447 | class="cm">// but we can handle the most common cases: |
| 448 | class="cm">// 1. completely overlapping rects |
| 449 | class="cm">// 2. adjacent rects that are the same width or height (e.g. items in a list) |
| 450 | class="cm">// |
| 451 | class="cm">// Even given the above constraints, |
| 452 | class="cm">// we still won't end up with the fewest possible rects without doing multiple passes, |
| 453 | class="cm">// but it's good enough for this purpose. |
| 454 | |
| 455 | if ( |
| 456 | targetLeft >= otherLeft && |
| 457 | targetTop >= otherTop && |
| 458 | targetRight <= otherRight && |
| 459 | targetBottom <= otherBottom |
| 460 | ) { |
| 461 | class="cm">// Complete overlapping rects; remove the inner one. |
| 462 | boundingRects.splice(i, 1); |
| 463 | break; |
| 464 | } else if ( |
| 465 | targetLeft === otherLeft && |
| 466 | targetRect.width === otherRect.width && |
| 467 | !(otherBottom < targetTop) && |
| 468 | !(otherTop > targetBottom) |
| 469 | ) { |
| 470 | class="cm">// Adjacent vertical rects; merge them. |
| 471 | if (otherTop > targetTop) { |
| 472 | otherRect.height += otherTop - targetTop; |
| 473 | otherRect.y = targetTop; |