mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-19 16:25:38 +00:00
Bug 1286464 part.3 Make static methods, AdjustTextRectNode() and GetFirstFrameInRange(), members of ContentEventHandler r=smaug
This patch makes the static methods members of ContentEventHandler because ContentEventHandler::NodePosition is useful for them. * nsINode* AdjustTextRectNode(nsINode*, int32_t&) -> NodePosition GetNodeHavingFlatText(nsINode* int32_t) * nsIFrame* GetFirstFrameInRange(nsRange*, int32_t&) -> FrameAndNodeOffset GetFirstFrameHavingFlatTextInRange(nsRange*) So, this patch avoids unclear in/out arguments of them. MozReview-Commit-ID: 7yWeIkRdGj --HG-- extra : rebase_source : 635cec95ee9f3d73f619186925464ae17010e929
This commit is contained in:
parent
24e9e4a700
commit
92692b4cb4
@ -1375,43 +1375,70 @@ ContentEventHandler::OnQueryTextContent(WidgetQueryContentEvent* aEvent)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Adjust to use a child node if possible
|
||||
// to make the returned rect more accurate
|
||||
static nsINode* AdjustTextRectNode(nsINode* aNode,
|
||||
int32_t& aNodeOffset)
|
||||
ContentEventHandler::NodePosition
|
||||
ContentEventHandler::GetNodePositionHavingFlatText(
|
||||
const NodePosition& aNodePosition)
|
||||
{
|
||||
int32_t childCount = int32_t(aNode->GetChildCount());
|
||||
nsINode* node = aNode;
|
||||
if (childCount) {
|
||||
if (aNodeOffset < childCount) {
|
||||
node = aNode->GetChildAt(aNodeOffset);
|
||||
aNodeOffset = 0;
|
||||
} else if (aNodeOffset == childCount) {
|
||||
node = aNode->GetChildAt(childCount - 1);
|
||||
aNodeOffset = node->IsNodeOfType(nsINode::eTEXT) ?
|
||||
static_cast<int32_t>(static_cast<nsIContent*>(node)->TextLength()) : 1;
|
||||
}
|
||||
}
|
||||
return node;
|
||||
return GetNodePositionHavingFlatText(aNodePosition.mNode,
|
||||
aNodePosition.mOffset);
|
||||
}
|
||||
|
||||
static
|
||||
nsIFrame*
|
||||
GetFirstFrameInRange(nsRange* aRange, int32_t& aNodeOffset)
|
||||
ContentEventHandler::NodePosition
|
||||
ContentEventHandler::GetNodePositionHavingFlatText(nsINode* aNode,
|
||||
int32_t aNodeOffset)
|
||||
{
|
||||
if (aNode->IsNodeOfType(nsINode::eTEXT)) {
|
||||
return NodePosition(aNode, aNodeOffset);
|
||||
}
|
||||
|
||||
int32_t childCount = static_cast<int32_t>(aNode->GetChildCount());
|
||||
|
||||
// If it's a empty element node, returns itself.
|
||||
if (!childCount) {
|
||||
MOZ_ASSERT(!aNodeOffset || aNodeOffset == 1);
|
||||
return NodePosition(aNode, aNodeOffset);
|
||||
}
|
||||
|
||||
// If there is a node at given position, return the start of it.
|
||||
if (aNodeOffset < childCount) {
|
||||
return NodePosition(aNode->GetChildAt(aNodeOffset), 0);
|
||||
}
|
||||
|
||||
// If the offset represents "after" the node, we need to return the last
|
||||
// child of it. For example, if a range is |<p>[<br>]</p>|, then, the
|
||||
// end point is {<p>, 1}. In such case, callers need the <br> node.
|
||||
if (aNodeOffset == childCount) {
|
||||
NodePosition result;
|
||||
result.mNode = aNode->GetChildAt(childCount - 1);
|
||||
result.mOffset = result.mNode->IsNodeOfType(nsINode::eTEXT) ?
|
||||
static_cast<int32_t>(result.mNode->AsContent()->TextLength()) : 1;
|
||||
}
|
||||
|
||||
NS_WARNING("aNodeOffset is invalid value");
|
||||
return NodePosition();
|
||||
}
|
||||
|
||||
ContentEventHandler::FrameAndNodeOffset
|
||||
ContentEventHandler::GetFirstFrameHavingFlatTextInRange(nsRange* aRange)
|
||||
{
|
||||
// used to iterate over all contents and their frames
|
||||
nsCOMPtr<nsIContentIterator> iter = NS_NewContentIterator();
|
||||
iter->Init(aRange);
|
||||
|
||||
// get the starting frame
|
||||
aNodeOffset = aRange->StartOffset();
|
||||
nsINode* node = iter->GetCurrentNode();
|
||||
if (!node) {
|
||||
node = AdjustTextRectNode(aRange->GetStartParent(), aNodeOffset);
|
||||
NodePosition nodePosition(iter->GetCurrentNode(), aRange->StartOffset());
|
||||
if (!nodePosition.mNode) {
|
||||
nodePosition =
|
||||
GetNodePositionHavingFlatText(aRange->GetStartParent(),
|
||||
nodePosition.mOffset);
|
||||
if (NS_WARN_IF(!nodePosition.IsValid())) {
|
||||
return FrameAndNodeOffset();
|
||||
}
|
||||
}
|
||||
nsIFrame* firstFrame = nullptr;
|
||||
GetFrameForTextRect(node, aNodeOffset, true, &firstFrame);
|
||||
return firstFrame;
|
||||
GetFrameForTextRect(nodePosition.mNode, nodePosition.mOffset,
|
||||
true, &firstFrame);
|
||||
return FrameAndNodeOffset(firstFrame, nodePosition.mOffset);
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -1436,9 +1463,8 @@ ContentEventHandler::OnQueryTextRectArray(WidgetQueryContentEvent* aEvent)
|
||||
}
|
||||
|
||||
// get the starting frame
|
||||
int32_t nodeOffset = -1;
|
||||
nsIFrame* firstFrame = GetFirstFrameInRange(range, nodeOffset);
|
||||
if (NS_WARN_IF(!firstFrame)) {
|
||||
FrameAndNodeOffset firstFrame = GetFirstFrameHavingFlatTextInRange(range);
|
||||
if (NS_WARN_IF(!firstFrame.IsValid())) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
@ -1450,8 +1476,8 @@ ContentEventHandler::OnQueryTextRectArray(WidgetQueryContentEvent* aEvent)
|
||||
}
|
||||
|
||||
AutoTArray<nsRect, 16> charRects;
|
||||
rv = firstFrame->GetCharacterRectsInRange(nodeOffset, kEndOffset - offset,
|
||||
charRects);
|
||||
rv = firstFrame->GetCharacterRectsInRange(firstFrame.mStartOffsetInNode,
|
||||
kEndOffset - offset, charRects);
|
||||
if (NS_WARN_IF(NS_FAILED(rv)) || NS_WARN_IF(charRects.IsEmpty())) {
|
||||
return rv;
|
||||
}
|
||||
@ -1498,13 +1524,18 @@ ContentEventHandler::OnQueryTextRect(WidgetQueryContentEvent* aEvent)
|
||||
iter->Init(range);
|
||||
|
||||
// get the starting frame
|
||||
int32_t nodeOffset = range->StartOffset();
|
||||
nsINode* node = iter->GetCurrentNode();
|
||||
if (!node) {
|
||||
node = AdjustTextRectNode(range->GetStartParent(), nodeOffset);
|
||||
NodePosition startNodePosition(iter->GetCurrentNode(), range->StartOffset());
|
||||
if (!startNodePosition.mNode) {
|
||||
startNodePosition =
|
||||
GetNodePositionHavingFlatText(range->GetStartParent(),
|
||||
startNodePosition.mOffset);
|
||||
if (NS_WARN_IF(!startNodePosition.IsValid())) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
nsIFrame* firstFrame = nullptr;
|
||||
rv = GetFrameForTextRect(node, nodeOffset, true, &firstFrame);
|
||||
rv = GetFrameForTextRect(startNodePosition.mNode, startNodePosition.mOffset,
|
||||
true, &firstFrame);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// get the starting frame rect
|
||||
@ -1513,7 +1544,7 @@ ContentEventHandler::OnQueryTextRect(WidgetQueryContentEvent* aEvent)
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsRect frameRect = rect;
|
||||
nsPoint ptOffset;
|
||||
firstFrame->GetPointFromOffset(nodeOffset, &ptOffset);
|
||||
firstFrame->GetPointFromOffset(startNodePosition.mOffset, &ptOffset);
|
||||
// minus 1 to avoid creating an empty rect
|
||||
if (firstFrame->GetWritingMode().IsVertical()) {
|
||||
rect.y += ptOffset.y - 1;
|
||||
@ -1524,10 +1555,14 @@ ContentEventHandler::OnQueryTextRect(WidgetQueryContentEvent* aEvent)
|
||||
}
|
||||
|
||||
// get the ending frame
|
||||
nodeOffset = range->EndOffset();
|
||||
node = AdjustTextRectNode(range->GetEndParent(), nodeOffset);
|
||||
NodePosition endNodePosition =
|
||||
GetNodePositionHavingFlatText(range->GetEndParent(), range->EndOffset());
|
||||
if (NS_WARN_IF(!endNodePosition.IsValid())) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
nsIFrame* lastFrame = nullptr;
|
||||
rv = GetFrameForTextRect(node, nodeOffset, range->Collapsed(), &lastFrame);
|
||||
rv = GetFrameForTextRect(endNodePosition.mNode, endNodePosition.mOffset,
|
||||
range->Collapsed(), &lastFrame);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// iterate over all covered frames
|
||||
@ -1536,14 +1571,14 @@ ContentEventHandler::OnQueryTextRect(WidgetQueryContentEvent* aEvent)
|
||||
if (!frame) {
|
||||
do {
|
||||
iter->Next();
|
||||
node = iter->GetCurrentNode();
|
||||
nsINode* node = iter->GetCurrentNode();
|
||||
if (!node) {
|
||||
break;
|
||||
}
|
||||
if (!node->IsNodeOfType(nsINode::eCONTENT)) {
|
||||
continue;
|
||||
}
|
||||
frame = static_cast<nsIContent*>(node)->GetPrimaryFrame();
|
||||
frame = node->AsContent()->GetPrimaryFrame();
|
||||
} while (!frame && !iter->IsDone());
|
||||
if (!frame) {
|
||||
// this can happen when the end offset of the range is 0.
|
||||
@ -1560,7 +1595,7 @@ ContentEventHandler::OnQueryTextRect(WidgetQueryContentEvent* aEvent)
|
||||
}
|
||||
|
||||
// get the ending frame rect
|
||||
lastFrame->GetPointFromOffset(nodeOffset, &ptOffset);
|
||||
lastFrame->GetPointFromOffset(endNodePosition.mOffset, &ptOffset);
|
||||
// minus 1 to avoid creating an empty rect
|
||||
if (lastFrame->GetWritingMode().IsVertical()) {
|
||||
frameRect.height -= lastFrame->GetRect().height - ptOffset.y - 1;
|
||||
|
@ -304,6 +304,43 @@ protected:
|
||||
nsresult QueryTextRectByRange(nsRange* aRange,
|
||||
LayoutDeviceIntRect& aRect,
|
||||
WritingMode& aWritingMode);
|
||||
|
||||
// Returns a node and position in the node for computing text rect.
|
||||
NodePosition GetNodePositionHavingFlatText(const NodePosition& aNodePosition);
|
||||
NodePosition GetNodePositionHavingFlatText(nsINode* aNode,
|
||||
int32_t aNodeOffset);
|
||||
|
||||
struct MOZ_STACK_CLASS FrameAndNodeOffset final
|
||||
{
|
||||
// mFrame is safe since this can live in only stack class and
|
||||
// ContentEventHandler doesn't modify layout after
|
||||
// ContentEventHandler::Init() flushes pending layout. In other words,
|
||||
// this struct shouldn't be used before calling
|
||||
// ContentEventHandler::Init().
|
||||
nsIFrame* mFrame;
|
||||
// Start offset in the node of mFrame
|
||||
int32_t mStartOffsetInNode;
|
||||
|
||||
FrameAndNodeOffset()
|
||||
: mFrame(nullptr)
|
||||
, mStartOffsetInNode(-1)
|
||||
{
|
||||
}
|
||||
|
||||
FrameAndNodeOffset(nsIFrame* aFrame, int32_t aStartOffsetInNode)
|
||||
: mFrame(aFrame)
|
||||
, mStartOffsetInNode(aStartOffsetInNode)
|
||||
{
|
||||
}
|
||||
|
||||
nsIFrame* operator->() { return mFrame; }
|
||||
const nsIFrame* operator->() const { return mFrame; }
|
||||
operator nsIFrame*() { return mFrame; }
|
||||
operator const nsIFrame*() const { return mFrame; }
|
||||
bool IsValid() const { return mFrame && mStartOffsetInNode >= 0; }
|
||||
};
|
||||
// Get first frame in the given range for computing text rect.
|
||||
FrameAndNodeOffset GetFirstFrameHavingFlatTextInRange(nsRange* aRange);
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
Loading…
Reference in New Issue
Block a user