Bug 1849007: Skip non-rendered characters in a11y cached character rects, since a11y only deals with rendered text. r=morgan

Differential Revision: https://phabricator.services.mozilla.com/D186521
This commit is contained in:
James Teh 2023-09-06 04:55:28 +00:00
parent ab691e8a10
commit 618a5cd667
2 changed files with 57 additions and 0 deletions

View file

@ -3550,6 +3550,22 @@ already_AddRefed<AccAttributes> LocalAccessible::BundleFieldsForCache(
currTextFrame->GetCharacterRectsInRange(
currTextFrame->GetContentOffset(), length, charBounds);
for (nsRect& charRect : charBounds) {
if (charRect.width == 0 &&
!currTextFrame->StyleText()->WhiteSpaceIsSignificant()) {
// GetCharacterRectsInRange gives us one rect per content
// offset. However, TextLeafAccessibles use rendered offsets;
// e.g. they might exclude some content white space. If we get
// a 0 width rect and it's white space, skip this rect, since
// this character isn't in the rendered text. We do have
// a way to convert between content and rendered offsets, but
// doing this for every character is expensive.
const char16_t contentChar = mContent->GetText()->CharAt(
charData.Length() / kNumbersInRect);
if (contentChar == u' ' || contentChar == u'\t' ||
contentChar == u'\n') {
continue;
}
}
// We expect each char rect to be relative to the text leaf
// acc this text lives in. Unfortunately, GetCharacterRectsInRange
// returns rects relative to their continuation. Add the

View file

@ -123,6 +123,27 @@ async function testTextRange(accDoc, browser, id, start, end) {
}
}
/**
* Since testTextChar can't handle non-rendered white space, this function first
* uses testTextChar to verify the first character and then ensures all
* characters thereafter have an incrementing x and a non-0 width.
*/
async function testLineWithNonRenderedSpace(docAcc, browser, id, length) {
await testChar(docAcc, browser, id, 0);
const acc = findAccessibleChildByID(docAcc, id, [nsIAccessibleText]);
let prevX = -1;
for (let offset = 0; offset < length; ++offset) {
const x = {};
const y = {};
const w = {};
const h = {};
acc.getCharacterExtents(offset, x, y, w, h, COORDTYPE_SCREEN_RELATIVE);
ok(x.value > prevX, `${id}: offset ${offset} x is larger (${x.value})`);
prevX = x.value;
ok(w.value > 0, `${id}: offset ${offset} width > 0`);
}
}
/**
* Test the text range boundary for simple LtR text
*/
@ -694,3 +715,23 @@ X</pre>`,
iframe: true,
}
);
/**
* Test character bounds where content white space isn't rendered.
*/
addAccessibleTask(
`
<p id="single">a b</p>
<p id="multi"><ins>a </ins>
b</p>
<pre id="pre">a b</pre>
`,
async function (browser, docAcc) {
await testLineWithNonRenderedSpace(docAcc, browser, "single", 3);
await testLineWithNonRenderedSpace(docAcc, browser, "multi", 2);
for (let offset = 0; offset < 4; ++offset) {
await testChar(docAcc, browser, "pre", offset);
}
},
{ chrome: true, topLevel: true }
);