Bug 1241631 - Don't trim leading whitespace from soft-wrapped lines when getting rendered text for a11y or .innerText. r=mats

Differential Revision: https://phabricator.services.mozilla.com/D45157

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Jonathan Kew 2019-09-17 17:36:13 +00:00
parent d03f6422fd
commit a8d927de19
2 changed files with 41 additions and 16 deletions

View File

@ -19,7 +19,7 @@
// __h__e__l__l__o__ __m__y__ __f__r__i__e__n__d__
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
var IDs = [ "i1", "d1", "e1", "t1" ];
var IDs = [ "i1", "d1", "d1wrap", "e1", "t1" ];
testCharacterCount(IDs, 15);
@ -96,6 +96,7 @@
<input id="i1" value="hello my friend"/>
<div id="d1">hello my friend</div>
<div id="d1wrap" style="word-wrap:break-word; width:1px">hello my friend</div>
<div id="e1" contenteditable="true">hello my friend</div>
<textarea id="t1">hello my friend</textarea>

View File

@ -9740,15 +9740,25 @@ static void TransformChars(nsTextFrame* aFrame, const nsStyleText* aStyle,
}
}
static bool LineEndsInHardLineBreak(nsTextFrame* aFrame,
nsBlockFrame* aLineContainer) {
static void LineStartsOrEndsAtHardLineBreak(nsTextFrame* aFrame,
nsBlockFrame* aLineContainer,
bool* aStartsAtHardBreak,
bool* aEndsAtHardBreak) {
bool foundValidLine;
nsBlockInFlowLineIterator iter(aLineContainer, aFrame, &foundValidLine);
if (!foundValidLine) {
NS_ERROR("Invalid line!");
return true;
*aStartsAtHardBreak = *aEndsAtHardBreak = true;
return;
}
*aEndsAtHardBreak = !iter.GetLine()->IsLineWrapped();
if (iter.Prev()) {
*aStartsAtHardBreak = !iter.GetLine()->IsLineWrapped();
} else {
// Hit block boundary
*aStartsAtHardBreak = true;
}
return !iter.GetLine()->IsLineWrapped();
}
nsIFrame::RenderedText nsTextFrame::GetRenderedText(
@ -9786,11 +9796,11 @@ nsIFrame::RenderedText nsTextFrame::GetRenderedText(
}
gfxSkipCharsIterator tmpIter = iter;
// Whether we need to trim whitespaces after the text frame.
bool trimAfter;
if (!textFrame->IsAtEndOfLine() ||
aTrimTrailingWhitespace != TrailingWhitespace::Trim) {
trimAfter = false;
// Check if the frame starts/ends at a hard line break, to determine
// whether whitespace should be trimmed.
bool startsAtHardBreak, endsAtHardBreak;
if (!(GetStateBits() & (TEXT_START_OF_LINE | TEXT_END_OF_LINE))) {
startsAtHardBreak = endsAtHardBreak = false;
} else if (nsBlockFrame* thisLc =
do_QueryFrame(FindLineContainer(textFrame))) {
if (thisLc != lineContainer) {
@ -9799,17 +9809,31 @@ nsIFrame::RenderedText nsTextFrame::GetRenderedText(
autoLineCursor.reset();
autoLineCursor.emplace(lineContainer);
}
trimAfter = LineEndsInHardLineBreak(textFrame, lineContainer);
LineStartsOrEndsAtHardLineBreak(textFrame, lineContainer,
&startsAtHardBreak, &endsAtHardBreak);
} else {
// Weird situation where we have a line layout without a block.
// No soft breaks occur in this situation.
trimAfter = true;
startsAtHardBreak = endsAtHardBreak = true;
}
// Skip to the start of the text run, past ignored chars at start of line
TrimmedOffsets trimmedOffsets = textFrame->GetTrimmedOffsets(
textFrag, (trimAfter ? TrimmedOffsetFlags::Default
: TrimmedOffsetFlags::NoTrimAfter));
// Whether we need to trim whitespaces after the text frame.
// TrimmedOffsetFlags::Default will allow trimming; we set NoTrim* flags
// in the cases where this should not occur.
TrimmedOffsetFlags trimFlags = TrimmedOffsetFlags::Default;
if (!textFrame->IsAtEndOfLine() ||
aTrimTrailingWhitespace != TrailingWhitespace::Trim ||
!endsAtHardBreak) {
trimFlags |= TrimmedOffsetFlags::NoTrimAfter;
}
// Whether to trim whitespaces before the text frame.
if (!startsAtHardBreak) {
trimFlags |= TrimmedOffsetFlags::NoTrimBefore;
}
TrimmedOffsets trimmedOffsets =
textFrame->GetTrimmedOffsets(textFrag, trimFlags);
bool trimmedSignificantNewline =
trimmedOffsets.GetEnd() < GetContentEnd() &&
HasSignificantTerminalNewline();