Bug 1286464 part.12 ContentEventHandler::GetFirstFrameHavingFlatTextInRange() should return only frames whose content causes text r=smaug

If it returns frames which don't cause text, the caller needs complicated loop. So, it should return only frames which causes some text.

MozReview-Commit-ID: 9gny0w1PUMa

--HG--
extra : rebase_source : 423c7b57355d659e1a5bd96dac35060cae38801c
This commit is contained in:
Masayuki Nakano 2016-07-21 17:45:17 +09:00
Родитель 925390facb
Коммит 0ee732da0b
2 изменённых файлов: 44 добавлений и 17 удалений

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

@ -1452,20 +1452,43 @@ ContentEventHandler::GetNodePositionHavingFlatText(nsINode* aNode,
ContentEventHandler::FrameAndNodeOffset
ContentEventHandler::GetFirstFrameHavingFlatTextInRange(nsRange* aRange)
{
// used to iterate over all contents and their frames
nsCOMPtr<nsIContentIterator> iter = NS_NewContentIterator();
iter->Init(aRange);
NodePosition nodePosition;
nsCOMPtr<nsIContentIterator> iter = NS_NewPreContentIterator();
for (iter->Init(aRange); !iter->IsDone(); iter->Next()) {
nsINode* node = iter->GetCurrentNode();
if (NS_WARN_IF(!node)) {
break;
}
// get the starting frame
NodePosition nodePosition(iter->GetCurrentNode(), aRange->StartOffset());
if (!nodePosition.mNode) {
nodePosition =
GetNodePositionHavingFlatText(aRange->GetStartParent(),
nodePosition.mOffset);
if (NS_WARN_IF(!nodePosition.IsValid())) {
return FrameAndNodeOffset();
if (!node->IsContent()) {
continue;
}
if (node->IsNodeOfType(nsINode::eTEXT)) {
// If the range starts at the end of a text node, we need to find
// next node which causes text.
int32_t offsetInNode =
node == aRange->GetStartParent() ? aRange->StartOffset() : 0;
if (static_cast<uint32_t>(offsetInNode) < node->Length()) {
nodePosition.mNode = node;
nodePosition.mOffset = offsetInNode;
break;
}
continue;
}
// If the element node causes a line break before it, it's the first
// node causing text.
if (ShouldBreakLineBefore(node->AsContent(), mRootContent)) {
nodePosition.mNode = node;
nodePosition.mOffset = 0;
}
}
if (!nodePosition.IsValid()) {
return FrameAndNodeOffset();
}
nsIFrame* firstFrame = nullptr;
GetFrameForTextRect(nodePosition.mNode, nodePosition.mOffset,
true, &firstFrame);
@ -1574,10 +1597,14 @@ ContentEventHandler::OnQueryTextRectArray(WidgetQueryContentEvent* aEvent)
// TODO: If the range is collapsed, that means offset reaches to the end
// of the contents. We need to do something here.
// get the starting frame
// Get the first frame which causes some text after the offset.
FrameAndNodeOffset firstFrame = GetFirstFrameHavingFlatTextInRange(range);
if (NS_WARN_IF(!firstFrame.IsValid())) {
return NS_ERROR_FAILURE;
// If GetFirstFrameHavingFlatTextInRange() does not return valid frame,
// that means that there is no remaining content which causes text.
// So, in such case, we must have reached the end of the contents.
if (!firstFrame.IsValid()) {
break;
}
nsIContent* firstContent = firstFrame.mFrame->GetContent();
@ -1621,8 +1648,6 @@ ContentEventHandler::OnQueryTextRectArray(WidgetQueryContentEvent* aEvent)
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

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

@ -339,7 +339,9 @@ protected:
operator const nsIFrame*() const { return mFrame; }
bool IsValid() const { return mFrame && mStartOffsetInNode >= 0; }
};
// Get first frame in the given range for computing text rect.
// Get first frame after the start of the given range for computing text rect.
// This returns invalid FrameAndNodeOffset if there is no content which
// causes text after the start of the range.
FrameAndNodeOffset GetFirstFrameHavingFlatTextInRange(nsRange* aRange);
struct MOZ_STACK_CLASS FrameRelativeRect final