Commit 8776a388 authored by Kevin Babbitt's avatar Kevin Babbitt Committed by Commit Bot

Remove redundant inner loop from AXRange::GetScreenRects

AXRange::GetScreenRects was written to handle cases where there are
multiple lines per text anchor, but in practice this never happens,
because each line of text gets its own InlineTextBox and thus its own
anchor. Removing the inner loop drastically reduces the runtime cost,
especially in cases where there are multiple nodes per line, since
CreateNextLineStart/EndPosition can become linear in the number of
nodes. On http://en.wikipedia.org I saw a 73% reduction in runtime for
this method with the inner loop removed.

Bug: 928948
Change-Id: I327d6369abaf0e697f8b9cf2156b9af2bcfce449
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1733794Reviewed-by: default avatarKurt Catti-Schmidt <kschmi@microsoft.com>
Reviewed-by: default avatarNektarios Paisios <nektar@chromium.org>
Commit-Queue: Kevin Babbitt <kbabbitt@microsoft.com>
Cr-Commit-Position: refs/heads/master@{#684182}
parent 8098d705
...@@ -264,61 +264,44 @@ class AXRange { ...@@ -264,61 +264,44 @@ class AXRange {
for (const AXRange& leaf_text_range : *this) { for (const AXRange& leaf_text_range : *this) {
DCHECK(!leaf_text_range.IsNull()); DCHECK(!leaf_text_range.IsNull());
AXPositionInstance current_end = AXPositionInstance current_line_end =
leaf_text_range.focus()->AsLeafTextPosition(); leaf_text_range.focus()->AsLeafTextPosition();
AXPositionInstance current_line_start = AXPositionInstance current_line_start =
leaf_text_range.anchor()->AsLeafTextPosition(); leaf_text_range.anchor()->AsLeafTextPosition();
while (current_line_start->GetAnchor() == current_end->GetAnchor() && if (current_line_start->GetAnchor()->data().role ==
*current_line_start <= *current_end) { ax::mojom::Role::kInlineTextBox) {
AXPositionInstance current_line_end = current_line_start = current_line_start->CreateParentPosition();
current_line_start->CreateNextLineEndPosition( current_line_end = current_line_end->CreateParentPosition();
ui::AXBoundaryBehavior::CrossBoundary);
if (current_line_end->GetAnchor() != current_end->GetAnchor() ||
*current_line_end > *current_end)
current_line_end = current_end->Clone();
DCHECK_LE(*current_line_start, *current_line_end);
DCHECK_LE(*current_line_end, *current_end);
if (current_line_start->GetAnchor()->data().role ==
ax::mojom::Role::kInlineTextBox) {
current_line_start = current_line_start->CreateParentPosition();
current_line_end = current_line_end->CreateParentPosition();
}
AXTreeID current_tree_id = current_line_start->tree_id();
AXTreeManager* manager =
AXTreeManagerMap::GetInstance().GetManager(current_tree_id);
AXPlatformNodeDelegate* current_anchor_delegate = manager->GetDelegate(
current_tree_id, current_line_start->anchor_id());
// For text anchors, we retrieve the bounding rectangles of its text
// content. For non-text anchors (such as checkboxes, images, etc.), we
// want to directly retrieve their bounding rectangles.
gfx::Rect current_rect =
(current_line_start->IsInLineBreak() ||
current_line_start->IsInTextObject())
? current_anchor_delegate->GetInnerTextRangeBoundsRect(
current_line_start->text_offset(),
current_line_end->text_offset(),
ui::AXCoordinateSystem::kScreen,
ui::AXClippingBehavior::kClipped)
: current_anchor_delegate->GetBoundsRect(
ui::AXCoordinateSystem::kScreen,
ui::AXClippingBehavior::kClipped);
// We only add rects that are visible within the current viewport.
// If the bounding rectangle is outside the viewport, the kClipped
// parameter from the bounds APIs will result in returning an empty
// rect, which we should omit from the final result.
if (!current_rect.IsEmpty())
rects.push_back(current_rect);
current_line_start = current_line_end->CreateNextLineStartPosition(
ui::AXBoundaryBehavior::CrossBoundary);
} }
AXTreeID current_tree_id = current_line_start->tree_id();
AXTreeManager* manager =
AXTreeManagerMap::GetInstance().GetManager(current_tree_id);
AXPlatformNodeDelegate* current_anchor_delegate = manager->GetDelegate(
current_tree_id, current_line_start->anchor_id());
// For text anchors, we retrieve the bounding rectangles of its text
// content. For non-text anchors (such as checkboxes, images, etc.), we
// want to directly retrieve their bounding rectangles.
gfx::Rect current_rect =
(current_line_start->IsInLineBreak() ||
current_line_start->IsInTextObject())
? current_anchor_delegate->GetInnerTextRangeBoundsRect(
current_line_start->text_offset(),
current_line_end->text_offset(),
ui::AXCoordinateSystem::kScreen,
ui::AXClippingBehavior::kClipped)
: current_anchor_delegate->GetBoundsRect(
ui::AXCoordinateSystem::kScreen,
ui::AXClippingBehavior::kClipped);
// We only add rects that are visible within the current viewport.
// If the bounding rectangle is outside the viewport, the kClipped
// parameter from the bounds APIs will result in returning an empty
// rect, which we should omit from the final result.
if (!current_rect.IsEmpty())
rects.push_back(current_rect);
} }
return rects; return rects;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment