/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// Build the chain of parents
Accessible* p1 = mContainer;
Accessible* p2 = aPoint.mContainer;
AutoTArray<Accessible*, 30> parents1, parents2; do {
parents1.AppendElement(p1);
p1 = p1->Parent();
} while (p1); do {
parents2.AppendElement(p2);
p2 = p2->Parent();
} while (p2);
// Find where the parent chain differs
uint32_t pos1 = parents1.Length(), pos2 = parents2.Length(); for (uint32_t len = std::min(pos1, pos2); len > 0; --len) {
Accessible* child1 = parents1.ElementAt(--pos1);
Accessible* child2 = parents2.ElementAt(--pos2); if (child1 != child2) { return child1->IndexInParent() < child2->IndexInParent();
}
}
if (pos1 != 0) { // If parents1 is a superset of parents2 then mContainer is a // descendant of aPoint.mContainer. The next element down in parents1 // is mContainer's ancestor that is the child of aPoint.mContainer. // We compare its end offset in aPoint.mContainer with aPoint.mOffset.
Accessible* child = parents1.ElementAt(pos1 - 1);
MOZ_ASSERT(child->Parent() == aPoint.mContainer); return child->EndOffset() < static_cast<uint32_t>(aPoint.mOffset);
}
if (pos2 != 0) { // If parents2 is a superset of parents1 then aPoint.mContainer is a // descendant of mContainer. The next element down in parents2 // is aPoint.mContainer's ancestor that is the child of mContainer. // We compare its start offset in mContainer with mOffset.
Accessible* child = parents2.ElementAt(pos2 - 1);
MOZ_ASSERT(child->Parent() == mContainer); returnstatic_cast<uint32_t>(mOffset) < child->StartOffset();
}
if (boundaryPos == 0) { if (containerPos != 0) { // The container is contained by the start boundary, reduce the range to // the point starting at the container.
ToTextPoint(aContainer, &mStartContainer, &mStartOffset);
} else { // The start boundary and the container are siblings.
container = aContainer;
}
} else { // The container does not contain the start boundary.
boundary = boundaryParents[boundaryPos];
container = containerParents[containerPos];
}
if (container) { // If the range start is after the container, then make the range invalid. if (boundary->IndexInParent() > container->IndexInParent()) { return !!(mRoot = nullptr);
}
// If the range starts before the container, then reduce the range to // the point starting at the container. if (boundary->IndexInParent() < container->IndexInParent()) {
ToTextPoint(container, &mStartContainer, &mStartOffset);
}
}
if (boundary->IndexInParent() < container->IndexInParent()) { return !!(mRoot = nullptr);
}
if (boundary->IndexInParent() > container->IndexInParent()) {
ToTextPoint(container, &mEndContainer, &mEndOffset, false);
}
returntrue;
}
/** * Convert the given DOM point to a DOM point in non-generated contents. * * If aDOMPoint is in ::before, the result is immediately after it. * If aDOMPoint is in ::after, the result is immediately before it.
*/ static DOMPoint ClosestNotGeneratedDOMPoint(const DOMPoint& aDOMPoint,
nsIContent* aElementContent) {
MOZ_ASSERT(aDOMPoint.node, "The node must not be null");
// ::before pseudo element if (aElementContent &&
aElementContent->IsGeneratedContentContainerForBefore()) {
MOZ_ASSERT(aElementContent->GetParent(), "::before must have parent element"); // The first child of its parent (i.e., immediately after the ::before) is // good point for a DOM range. return DOMPoint(aElementContent->GetParent(), 0);
}
// ::after pseudo element if (aElementContent &&
aElementContent->IsGeneratedContentContainerForAfter()) {
MOZ_ASSERT(aElementContent->GetParent(), "::after must have parent element"); // The end of its parent (i.e., immediately before the ::after) is good // point for a DOM range. return DOMPoint(aElementContent->GetParent(),
aElementContent->GetParent()->GetChildCount());
}
return aDOMPoint;
}
/** * GetElementAsContentOf() returns a content representing an element which is * or includes aNode. * * XXX This method is enough to retrieve ::before or ::after pseudo element. * So, if you want to use this for other purpose, you might need to check * ancestors too.
*/ static nsIContent* GetElementAsContentOf(nsINode* aNode) { if (auto* element = dom::Element::FromNode(aNode)) { return element;
} return aNode->GetParentElement();
}
// HyperTextAccessible manages pseudo elements generated by ::before or // ::after. However, contents of them are not in the DOM tree normally. // Therefore, they are not selectable and editable. So, when this creates // a DOM range, it should not start from nor end in any pseudo contents.
// If the caller wants collapsed range, let's collapse the range to its start. if (mEndContainer == mStartContainer && mEndOffset == mStartOffset) {
aRange->Collapse(true); returntrue;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.