Bug 1730862 part 1: Make HyperTextAccessibleBase::TransformOffset easier to use. r=eeejay

1. When calculating a start offset, we usually want 0 if the offset can't be transformed, thus clipping to the start of this Accessible.
    Previously, CharacterCount was always returned even when calculating a start offset.
    Now, we return 0 for a start offset, CharacterCount for an end offset.
2. Sometimes, this fallback value is insufficient and we need to know explicitly whether it failed.
    As well as the offset, we now return a boolean indicating this.
    This will be used in a subsequent patch.
3. Even though TransformOffset only deals with positive numbers, callers usually deal with signed numbers.
    Therefore, we now use int32_t insteaed of uint32_t to avoid a lot of casting.

Differential Revision: https://phabricator.services.mozilla.com/D132094
This commit is contained in:
James Teh 2021-11-30 02:07:36 +00:00
Родитель 88c83e9a81
Коммит ab3b1b2ccc
2 изменённых файлов: 26 добавлений и 37 удалений

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

@ -182,17 +182,16 @@ TextLeafPoint HyperTextAccessibleBase::ToTextLeafPoint(int32_t aOffset,
return TextLeafPoint(child, offset); return TextLeafPoint(child, offset);
} }
uint32_t HyperTextAccessibleBase::TransformOffset(Accessible* aDescendant, std::pair<bool, int32_t> HyperTextAccessibleBase::TransformOffset(
uint32_t aOffset, Accessible* aDescendant, int32_t aOffset, bool aIsEndOffset) const {
bool aIsEndOffset) const {
const Accessible* thisAcc = Acc(); const Accessible* thisAcc = Acc();
// From the descendant, go up and get the immediate child of this hypertext. // From the descendant, go up and get the immediate child of this hypertext.
uint32_t offset = aOffset; int32_t offset = aOffset;
Accessible* descendant = aDescendant; Accessible* descendant = aDescendant;
while (descendant) { while (descendant) {
Accessible* parent = descendant->Parent(); Accessible* parent = descendant->Parent();
if (parent == thisAcc) { if (parent == thisAcc) {
return GetChildOffset(descendant) + offset; return {true, GetChildOffset(descendant) + offset};
} }
// This offset no longer applies because the passed-in text object is not // This offset no longer applies because the passed-in text object is not
@ -211,9 +210,10 @@ uint32_t HyperTextAccessibleBase::TransformOffset(Accessible* aDescendant,
descendant = parent; descendant = parent;
} }
// If the given a11y point cannot be mapped into offset relative this // The given a11y point cannot be mapped to an offset relative to this
// hypertext offset then return length as fallback value. // hypertext accessible. Return the start or the end depending on whether this
return CharacterCount(); // is a start ofset or an end offset, thus clipping to the relevant endpoint.
return {false, aIsEndOffset ? static_cast<int32_t>(CharacterCount()) : 0};
} }
void HyperTextAccessibleBase::TextAtOffset(int32_t aOffset, void HyperTextAccessibleBase::TextAtOffset(int32_t aOffset,
@ -257,21 +257,12 @@ void HyperTextAccessibleBase::TextAtOffset(int32_t aOffset,
} }
TextLeafPoint start = origStart.FindBoundary(aBoundaryType, eDirPrevious, TextLeafPoint start = origStart.FindBoundary(aBoundaryType, eDirPrevious,
/* aIncludeOrigin */ true); /* aIncludeOrigin */ true);
*aStartOffset = bool ok;
static_cast<int32_t>(TransformOffset(start.mAcc, start.mOffset, std::tie(ok, *aStartOffset) = TransformOffset(start.mAcc, start.mOffset,
/* aIsEndOffset */ false)); /* aIsEndOffset */ false);
if (*aStartOffset == static_cast<int32_t>(CharacterCount()) &&
(*aStartOffset > static_cast<int32_t>(adjustedOffset) ||
start != origStart)) {
// start is before this HyperTextAccessible. In that case,
// Transformoffset will return CharacterCount(), but we want to
// clip to the start of this HyperTextAccessible, not the end.
*aStartOffset = 0;
}
end = end.FindBoundary(aBoundaryType, eDirNext); end = end.FindBoundary(aBoundaryType, eDirNext);
*aEndOffset = std::tie(ok, *aEndOffset) = TransformOffset(end.mAcc, end.mOffset,
static_cast<int32_t>(TransformOffset(end.mAcc, end.mOffset, /* aIsEndOffset */ true);
/* aIsEndOffset */ true));
TextSubstring(*aStartOffset, *aEndOffset, aText); TextSubstring(*aStartOffset, *aEndOffset, aText);
return; return;
} }
@ -355,20 +346,13 @@ already_AddRefed<AccAttributes> HyperTextAccessibleBase::TextAttributes(
RefPtr<AccAttributes> attributes = origin.GetTextAttributes(aIncludeDefAttrs); RefPtr<AccAttributes> attributes = origin.GetTextAttributes(aIncludeDefAttrs);
TextLeafPoint start = origin.FindTextAttrsStart( TextLeafPoint start = origin.FindTextAttrsStart(
eDirPrevious, /* aIncludeOrigin */ true, attributes, aIncludeDefAttrs); eDirPrevious, /* aIncludeOrigin */ true, attributes, aIncludeDefAttrs);
*aStartOffset = bool ok;
static_cast<int32_t>(TransformOffset(start.mAcc, start.mOffset, std::tie(ok, *aStartOffset) = TransformOffset(start.mAcc, start.mOffset,
/* aIsEndOffset */ false)); /* aIsEndOffset */ false);
if (*aStartOffset == static_cast<int32_t>(CharacterCount()) &&
(*aStartOffset > static_cast<int32_t>(offset) || start != origin)) {
// start is before this HyperTextAccessible. In that case,
// Transformoffset will return CharacterCount(), but we want to
// clip to the start of this HyperTextAccessible, not the end.
*aStartOffset = 0;
}
TextLeafPoint end = origin.FindTextAttrsStart( TextLeafPoint end = origin.FindTextAttrsStart(
eDirNext, /* aIncludeOrigin */ false, attributes, aIncludeDefAttrs); eDirNext, /* aIncludeOrigin */ false, attributes, aIncludeDefAttrs);
*aEndOffset = static_cast<int32_t>(TransformOffset(end.mAcc, end.mOffset, std::tie(ok, *aEndOffset) = TransformOffset(end.mAcc, end.mOffset,
/* aIsEndOffset */ true)); /* aIsEndOffset */ true);
return attributes.forget(); return attributes.forget();
} }

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

@ -148,10 +148,15 @@ class HyperTextAccessibleBase {
private: private:
/** /**
* Transform the given a11y point into the offset relative this hypertext. * Transform the given a11y point into an offset relative to this hypertext.
* Returns {success, offset}, where success is true if successful.
* If unsuccessful, the returned offset will be CharacterCount() if
* aIsEndOffset is true, 0 otherwise. This means most callers can ignore the
* success return value.
*/ */
uint32_t TransformOffset(Accessible* aDescendant, uint32_t aOffset, std::pair<bool, int32_t> TransformOffset(Accessible* aDescendant,
bool aIsEndOffset) const; int32_t aOffset,
bool aIsEndOffset) const;
}; };
} // namespace mozilla::a11y } // namespace mozilla::a11y