Bug 1820029: Inline HyperTextAccessible::TextBounds to TextLeafPoint::CharBounds r=Jamie

Differential Revision: https://phabricator.services.mozilla.com/D171503
This commit is contained in:
Morgan Rae Reschenberg 2023-03-09 19:59:00 +00:00
Родитель f77b49974e
Коммит 60f92a62cb
2 изменённых файлов: 85 добавлений и 5 удалений

Просмотреть файл

@ -17,6 +17,7 @@
#include "mozilla/dom/CharacterData.h"
#include "mozilla/dom/Document.h"
#include "mozilla/dom/HTMLInputElement.h"
#include "mozilla/PresShell.h"
#include "mozilla/intl/Segmenter.h"
#include "mozilla/intl/WordBreaker.h"
#include "mozilla/StaticPrefs_layout.h"
@ -1462,6 +1463,55 @@ TextLeafPoint TextLeafPoint::NeighborLeafPoint(
: 0);
}
LayoutDeviceIntRect TextLeafPoint::ComputeBoundsFromFrame() const {
LocalAccessible* local = mAcc->AsLocal();
MOZ_ASSERT(local, "Can't compute bounds in frame from non-local acc");
nsIFrame* frame = local->GetFrame();
MOZ_ASSERT(frame, "No frame found for acc!");
if (!frame->IsTextFrame()) {
return local->Bounds();
}
// Substring must be entirely within the same text node.
MOZ_ASSERT(frame->IsPrimaryFrame(),
"Cannot compute content offset on non-primary frame");
nsIFrame::RenderedText text = frame->GetRenderedText(
mOffset, mOffset + 1, nsIFrame::TextOffsetType::OffsetsInRenderedText,
nsIFrame::TrailingWhitespace::DontTrim);
int32_t contentOffset = text.mOffsetWithinNodeText;
int32_t contentOffsetInFrame;
// Get the right frame continuation -- not really a child, but a sibling of
// the primary frame passed in
nsresult rv = frame->GetChildFrameContainingOffset(
contentOffset, false, &contentOffsetInFrame, &frame);
NS_ENSURE_SUCCESS(rv, LayoutDeviceIntRect());
// Start with this frame's screen rect, which we will shrink based on
// the char we care about within it.
nsRect frameScreenRect = frame->GetScreenRectInAppUnits();
// Add the point where the char starts to the frameScreenRect
nsPoint frameTextStartPoint;
rv = frame->GetPointFromOffset(contentOffset, &frameTextStartPoint);
NS_ENSURE_SUCCESS(rv, LayoutDeviceIntRect());
// Use the next offset to calculate the width
// XXX(morgan) does this work for vertical text?
nsPoint frameTextEndPoint;
rv = frame->GetPointFromOffset(contentOffset + 1, &frameTextEndPoint);
NS_ENSURE_SUCCESS(rv, LayoutDeviceIntRect());
frameScreenRect.SetRectX(
frameScreenRect.X() +
std::min(frameTextStartPoint.x, frameTextEndPoint.x),
mozilla::Abs(frameTextStartPoint.x - frameTextEndPoint.x));
nsPresContext* presContext = local->Document()->PresContext();
return LayoutDeviceIntRect::FromAppUnitsToNearest(
frameScreenRect, presContext->AppUnitsPerDevPixel());
}
/* static */
nsTArray<int32_t> TextLeafPoint::GetSpellingErrorOffsets(
LocalAccessible* aAcc) {
@ -1660,11 +1710,32 @@ LayoutDeviceIntRect TextLeafPoint::CharBounds() {
}
if (LocalAccessible* local = mAcc->AsLocal()) {
HyperTextAccessible* ht = HyperTextFor(local);
MOZ_ASSERT(ht, "Could not find hypertext for text acc?");
return ht->CharBounds(
static_cast<int32_t>(ht->TransformOffset(local, mOffset, true)),
nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE);
if (!local->IsTextLeaf() || nsAccUtils::TextLength(local) == 0) {
// Empty content, use our own bounds to at least get x,y coordinates
return local->Bounds();
}
if (mOffset >= 0 &&
static_cast<uint32_t>(mOffset) > nsAccUtils::TextLength(local)) {
NS_ERROR("Wrong in offset");
return LayoutDeviceIntRect();
}
LayoutDeviceIntRect bounds = ComputeBoundsFromFrame();
// This document may have a resolution set, we will need to multiply
// the document-relative coordinates by that value and re-apply the doc's
// screen coordinates.
nsPresContext* presContext = local->Document()->PresContext();
nsIFrame* rootFrame = presContext->PresShell()->GetRootFrame();
LayoutDeviceIntRect orgRectPixels =
LayoutDeviceIntRect::FromAppUnitsToNearest(
rootFrame->GetScreenRectInAppUnits(),
presContext->AppUnitsPerDevPixel());
bounds.MoveBy(-orgRectPixels.X(), -orgRectPixels.Y());
bounds.ScaleRoundOut(presContext->PresShell()->GetResolution());
bounds.MoveBy(orgRectPixels.X(), orgRectPixels.Y());
return bounds;
}
RemoteAccessible* remote = mAcc->AsRemote();

Просмотреть файл

@ -236,6 +236,15 @@ class TextLeafPoint final {
// on given direction.
TextLeafPoint NeighborLeafPoint(nsDirection aDirection, bool aIsEditable,
bool aIgnoreListItemMarker) const;
/**
* This function assumes mAcc is a LocalAccessible.
* It iterates the continuations of mAcc's primary frame until it locates
* the continuation containing mOffset (a rendered offset). It then uses
* GetScreenRectInAppUnits to compute screen coords for the frame, resizing
* such that the resulting rect contains only one character.
*/
LayoutDeviceIntRect ComputeBoundsFromFrame() const;
};
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(TextLeafPoint::BoundaryFlags)