Bug 1286464 part.10 ContentEventHandler::OnQueryTextRectArray() should append same rects for following characters of a line breaker in nsTextFrame r=smaug
If line breakers in a text node works as is, e.g., |white-space: pre;| is specified, we need to handle line breakers in text frames too.
This patch handles "\n" in text nodes same as line breakers caused by some elements.
MozReview-Commit-ID: JmXesusFxzR
--- a/dom/events/ContentEventHandler.cpp
+++ b/dom/events/ContentEventHandler.cpp
@@ -1588,25 +1588,26 @@ ContentEventHandler::OnQueryTextRectArra
// get the starting frame rect
nsRect frameRect(nsPoint(0, 0), firstFrame->GetRect().Size());
rv = ConvertToRootRelativeOffset(firstFrame, frameRect);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
bool startsBetweenLineBreaker = false;
+ nsAutoString chars;
AutoTArray<nsRect, 16> charRects;
- bool isLineBreaker = ShouldBreakLineBefore(firstContent, mRootContent);
- if (isLineBreaker) {
+ if (ShouldBreakLineBefore(firstContent, mRootContent)) {
// TODO: If the frame isn't <br> and there was previous text frame or
// <br>, we can set the rect to caret rect at the end. Currently,
// this sets the rect to caret rect at the start of the node.
FrameRelativeRect brRect = GetLineBreakerRectBefore(firstFrame);
charRects.AppendElement(brRect.RectRelativeTo(firstFrame));
+ chars.AssignLiteral("\n");
if (kBRLength > 1 && offset == aEvent->mInput.mOffset && offset) {
// If the first frame for the previous offset of the query range and
// the first frame for the start of query range are same, that means
// the start offset is between the first line breaker (i.e., the range
// starts between "\r" and "\n").
rv = SetRangeFromFlatTextOffset(range, aEvent->mInput.mOffset - 1, 1,
lineBreakType, true, nullptr);
if (NS_WARN_IF(NS_FAILED(rv))) {
@@ -1619,16 +1620,40 @@ ContentEventHandler::OnQueryTextRectArra
} else {
rv = firstFrame->GetCharacterRectsInRange(firstFrame.mStartOffsetInNode,
kEndOffset - offset, charRects);
if (NS_WARN_IF(NS_FAILED(rv)) || NS_WARN_IF(charRects.IsEmpty())) {
// XXX: If the node isn't a text node and does not cause a line break,
// we need to recompute with new range, but how?
return rv;
}
+ // Assign the characters whose rects are computed by the call of
+ // nsTextFrame::GetCharacterRectsInRange().
+ AppendSubString(chars, firstContent, firstFrame.mStartOffsetInNode,
+ charRects.Length());
+ if (NS_WARN_IF(chars.Length() != charRects.Length())) {
+ return NS_ERROR_UNEXPECTED;
+ }
+ if (kBRLength > 1 && chars[0] == '\n' &&
+ offset == aEvent->mInput.mOffset && offset) {
+ // If start of range starting from previous offset of query range is
+ // same as the start of query range, the query range starts from
+ // between a line breaker (i.e., the range starts between "\r" and
+ // "\n").
+ RefPtr<nsRange> rangeToPrevOffset = new nsRange(mRootContent);
+ rv = SetRangeFromFlatTextOffset(rangeToPrevOffset,
+ aEvent->mInput.mOffset - 1, 1,
+ lineBreakType, true, nullptr);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+ startsBetweenLineBreaker =
+ range->GetStartParent() == rangeToPrevOffset->GetStartParent() &&
+ range->StartOffset() == rangeToPrevOffset->StartOffset();
+ }
}
for (size_t i = 0; i < charRects.Length() && offset < kEndOffset; i++) {
nsRect charRect = charRects[i];
charRect.x += frameRect.x;
charRect.y += frameRect.y;
rect = LayoutDeviceIntRect::FromUnknownRect(
@@ -1637,17 +1662,17 @@ ContentEventHandler::OnQueryTextRectArra
// return non-empty rect.
EnsureNonEmptyRect(rect);
aEvent->mReply.mRectArray.AppendElement(rect);
offset++;
// If it's not a line breaker or the line breaker length is same as
// XP line breaker's, we need to do nothing for current character.
- if (!isLineBreaker || kBRLength == 1) {
+ if (chars[i] != '\n' || kBRLength == 1) {
continue;
}
MOZ_ASSERT(kBRLength == 2);
// If it's already reached the end of query range, we don't need to do
// anymore.
if (offset == kEndOffset) {