Commit 86b71ef1 authored by yosin@chromium.org's avatar yosin@chromium.org

Move computeInlineBoxPosition() to VisibleUnits.{cpp,h} from Position.{cpp,h} and VisiblePosition.h

This patch moves |computeInlineBoxPosition()| to "VisibleUnits.{cpp,h} from
"Position.{cpp,h}" and "VisiblePosition.{cpp,h}" to consolidate |InlineBox|
dependency to "VisibleUnits.cpp" for ease of working them later.

BUG=518738
TEST=n/a; no behavior changes

Review URL: https://codereview.chromium.org/1303173002

git-svn-id: svn://svn.chromium.org/blink/trunk@200970 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent dcb20b16
...@@ -599,256 +599,6 @@ bool inRenderedText(const PositionInComposedTree& position) ...@@ -599,256 +599,6 @@ bool inRenderedText(const PositionInComposedTree& position)
return inRenderedTextAlgorithm<EditingInComposedTreeStrategy>(position); return inRenderedTextAlgorithm<EditingInComposedTreeStrategy>(position);
} }
template <typename Strategy>
static InlineBoxPosition computeInlineBoxPositionAlgorithm(const PositionAlgorithm<Strategy>& position, TextAffinity affinity)
{
return computeInlineBoxPositionAlgorithm<Strategy>(position, affinity, primaryDirectionOf(*position.anchorNode()));
}
InlineBoxPosition computeInlineBoxPosition(const Position& position, TextAffinity affinity)
{
return computeInlineBoxPositionAlgorithm<EditingStrategy>(position, affinity);
}
InlineBoxPosition computeInlineBoxPosition(const PositionInComposedTree& position, TextAffinity affinity)
{
return computeInlineBoxPositionAlgorithm<EditingInComposedTreeStrategy>(position, affinity);
}
static bool isNonTextLeafChild(LayoutObject* object)
{
if (object->slowFirstChild())
return false;
if (object->isText())
return false;
return true;
}
static InlineTextBox* searchAheadForBetterMatch(LayoutObject* layoutObject)
{
LayoutBlock* container = layoutObject->containingBlock();
for (LayoutObject* next = layoutObject->nextInPreOrder(container); next; next = next->nextInPreOrder(container)) {
if (next->isLayoutBlock())
return 0;
if (next->isBR())
return 0;
if (isNonTextLeafChild(next))
return 0;
if (next->isText()) {
InlineTextBox* match = 0;
int minOffset = INT_MAX;
for (InlineTextBox* box = toLayoutText(next)->firstTextBox(); box; box = box->nextTextBox()) {
int caretMinOffset = box->caretMinOffset();
if (caretMinOffset < minOffset) {
match = box;
minOffset = caretMinOffset;
}
}
if (match)
return match;
}
}
return 0;
}
template <typename Strategy>
PositionAlgorithm<Strategy> downstreamIgnoringEditingBoundaries(PositionAlgorithm<Strategy> position)
{
PositionAlgorithm<Strategy> lastPosition;
while (position != lastPosition) {
lastPosition = position;
position = position.downstream(CanCrossEditingBoundary);
}
return position;
}
template <typename Strategy>
PositionAlgorithm<Strategy> upstreamIgnoringEditingBoundaries(PositionAlgorithm<Strategy> position)
{
PositionAlgorithm<Strategy> lastPosition;
while (position != lastPosition) {
lastPosition = position;
position = position.upstream(CanCrossEditingBoundary);
}
return position;
}
template <typename Strategy>
static InlineBoxPosition computeInlineBoxPositionAlgorithm(const PositionAlgorithm<Strategy>& position, TextAffinity affinity, TextDirection primaryDirection)
{
InlineBox* inlineBox = nullptr;
int caretOffset = position.computeEditingOffset();
Node* const anchorNode = position.anchorNode();
LayoutObject* layoutObject = anchorNode->isShadowRoot() ? toShadowRoot(anchorNode)->host()->layoutObject() : anchorNode->layoutObject();
if (!layoutObject->isText()) {
inlineBox = 0;
if (canHaveChildrenForEditing(anchorNode) && layoutObject->isLayoutBlockFlow() && hasRenderedNonAnonymousDescendantsWithHeight(layoutObject)) {
// Try a visually equivalent position with possibly opposite
// editability. This helps in case |this| is in an editable block
// but surrounded by non-editable positions. It acts to negate the
// logic at the beginning of LayoutObject::createVisiblePosition().
PositionAlgorithm<Strategy> equivalent = downstreamIgnoringEditingBoundaries(position);
if (equivalent == position) {
equivalent = upstreamIgnoringEditingBoundaries(position);
if (equivalent == position || downstreamIgnoringEditingBoundaries(equivalent) == position)
return InlineBoxPosition(inlineBox, caretOffset);
}
return computeInlineBoxPosition(equivalent, TextAffinity::Upstream, primaryDirection);
}
if (layoutObject->isBox()) {
inlineBox = toLayoutBox(layoutObject)->inlineBoxWrapper();
if (!inlineBox || (caretOffset > inlineBox->caretMinOffset() && caretOffset < inlineBox->caretMaxOffset()))
return InlineBoxPosition(inlineBox, caretOffset);
}
} else {
LayoutText* textLayoutObject = toLayoutText(layoutObject);
InlineTextBox* box;
InlineTextBox* candidate = 0;
for (box = textLayoutObject->firstTextBox(); box; box = box->nextTextBox()) {
int caretMinOffset = box->caretMinOffset();
int caretMaxOffset = box->caretMaxOffset();
if (caretOffset < caretMinOffset || caretOffset > caretMaxOffset || (caretOffset == caretMaxOffset && box->isLineBreak()))
continue;
if (caretOffset > caretMinOffset && caretOffset < caretMaxOffset)
return InlineBoxPosition(box, caretOffset);
if (((caretOffset == caretMaxOffset) ^ (affinity == TextAffinity::Downstream))
|| ((caretOffset == caretMinOffset) ^ (affinity == TextAffinity::Upstream))
|| (caretOffset == caretMaxOffset && box->nextLeafChild() && box->nextLeafChild()->isLineBreak()))
break;
candidate = box;
}
if (candidate && candidate == textLayoutObject->lastTextBox() && affinity == TextAffinity::Downstream) {
box = searchAheadForBetterMatch(textLayoutObject);
if (box)
caretOffset = box->caretMinOffset();
}
inlineBox = box ? box : candidate;
}
if (!inlineBox)
return InlineBoxPosition(inlineBox, caretOffset);
unsigned char level = inlineBox->bidiLevel();
if (inlineBox->direction() == primaryDirection) {
if (caretOffset == inlineBox->caretRightmostOffset()) {
InlineBox* nextBox = inlineBox->nextLeafChild();
if (!nextBox || nextBox->bidiLevel() >= level)
return InlineBoxPosition(inlineBox, caretOffset);
level = nextBox->bidiLevel();
InlineBox* prevBox = inlineBox;
do {
prevBox = prevBox->prevLeafChild();
} while (prevBox && prevBox->bidiLevel() > level);
// For example, abc FED 123 ^ CBA
if (prevBox && prevBox->bidiLevel() == level)
return InlineBoxPosition(inlineBox, caretOffset);
// For example, abc 123 ^ CBA
while (InlineBox* nextBox = inlineBox->nextLeafChild()) {
if (nextBox->bidiLevel() < level)
break;
inlineBox = nextBox;
}
return InlineBoxPosition(inlineBox, inlineBox->caretRightmostOffset());
}
InlineBox* prevBox = inlineBox->prevLeafChild();
if (!prevBox || prevBox->bidiLevel() >= level)
return InlineBoxPosition(inlineBox, caretOffset);
level = prevBox->bidiLevel();
InlineBox* nextBox = inlineBox;
do {
nextBox = nextBox->nextLeafChild();
} while (nextBox && nextBox->bidiLevel() > level);
if (nextBox && nextBox->bidiLevel() == level)
return InlineBoxPosition(inlineBox, caretOffset);
while (InlineBox* prevBox = inlineBox->prevLeafChild()) {
if (prevBox->bidiLevel() < level)
break;
inlineBox = prevBox;
}
return InlineBoxPosition(inlineBox, inlineBox->caretLeftmostOffset());
}
if (caretOffset == inlineBox->caretLeftmostOffset()) {
InlineBox* prevBox = inlineBox->prevLeafChildIgnoringLineBreak();
if (!prevBox || prevBox->bidiLevel() < level) {
// Left edge of a secondary run. Set to the right edge of the entire
// run.
while (InlineBox* nextBox = inlineBox->nextLeafChildIgnoringLineBreak()) {
if (nextBox->bidiLevel() < level)
break;
inlineBox = nextBox;
}
return InlineBoxPosition(inlineBox, inlineBox->caretRightmostOffset());
}
if (prevBox->bidiLevel() > level) {
// Right edge of a "tertiary" run. Set to the left edge of that run.
while (InlineBox* tertiaryBox = inlineBox->prevLeafChildIgnoringLineBreak()) {
if (tertiaryBox->bidiLevel() <= level)
break;
inlineBox = tertiaryBox;
}
return InlineBoxPosition(inlineBox, inlineBox->caretLeftmostOffset());
}
return InlineBoxPosition(inlineBox, caretOffset);
}
if (layoutObject && layoutObject->style()->unicodeBidi() == Plaintext) {
if (inlineBox->bidiLevel() < level)
return InlineBoxPosition(inlineBox, inlineBox->caretLeftmostOffset());
return InlineBoxPosition(inlineBox, inlineBox->caretRightmostOffset());
}
InlineBox* nextBox = inlineBox->nextLeafChildIgnoringLineBreak();
if (!nextBox || nextBox->bidiLevel() < level) {
// Right edge of a secondary run. Set to the left edge of the entire
// run.
while (InlineBox* prevBox = inlineBox->prevLeafChildIgnoringLineBreak()) {
if (prevBox->bidiLevel() < level)
break;
inlineBox = prevBox;
}
return InlineBoxPosition(inlineBox, inlineBox->caretLeftmostOffset());
}
if (nextBox->bidiLevel() <= level)
return InlineBoxPosition(inlineBox, caretOffset);
// Left edge of a "tertiary" run. Set to the right edge of that run.
while (InlineBox* tertiaryBox = inlineBox->nextLeafChildIgnoringLineBreak()) {
if (tertiaryBox->bidiLevel() <= level)
break;
inlineBox = tertiaryBox;
}
return InlineBoxPosition(inlineBox, inlineBox->caretRightmostOffset());
}
InlineBoxPosition computeInlineBoxPosition(const Position& position, TextAffinity affinity, TextDirection primaryDirection)
{
return computeInlineBoxPositionAlgorithm<EditingStrategy>(position, affinity, primaryDirection);
}
InlineBoxPosition computeInlineBoxPosition(const PositionInComposedTree& position, TextAffinity affinity, TextDirection primaryDirection)
{
return computeInlineBoxPositionAlgorithm<EditingInComposedTreeStrategy>(position, affinity, primaryDirection);
}
template <typename Strategy> template <typename Strategy>
void PositionAlgorithm<Strategy>::debugPosition(const char* msg) const void PositionAlgorithm<Strategy>::debugPosition(const char* msg) const
{ {
......
...@@ -39,28 +39,12 @@ ...@@ -39,28 +39,12 @@
namespace blink { namespace blink {
class Element; class Element;
class InlineBox;
class Node; class Node;
class LayoutObject; class LayoutObject;
class Text; class Text;
enum class TextAffinity; enum class TextAffinity;
class TreeScope; class TreeScope;
struct InlineBoxPosition {
InlineBox* inlineBox;
int offsetInBox;
InlineBoxPosition()
: inlineBox(nullptr), offsetInBox(0)
{
}
InlineBoxPosition(InlineBox* inlineBox, int offsetInBox)
: inlineBox(inlineBox), offsetInBox(offsetInBox)
{
}
};
enum PositionMoveType { enum PositionMoveType {
CodePoint, // Move by a single code point. CodePoint, // Move by a single code point.
Character, // Move to the next Unicode character break. Character, // Move to the next Unicode character break.
...@@ -423,17 +407,6 @@ inline PositionInComposedTree fromPositionInDOMTree<EditingInComposedTreeStrateg ...@@ -423,17 +407,6 @@ inline PositionInComposedTree fromPositionInDOMTree<EditingInComposedTreeStrateg
return toPositionInComposedTree(position); return toPositionInComposedTree(position);
} }
// TODO(yosin) |isRenderedCharacter()| should be removed, and we should use
// |VisiblePosition::characterAfter()| and |VisiblePosition::characterBefore()|.
// TODO(yosin) We should move |isRenderedCharacter()| to "VisibleUnits.cpp",
// since it is used only in "editing/commands/"
CORE_EXPORT bool isRenderedCharacter(const Position&);
// TODO(yosin) We should move |computeInlineBoxPosition()| to "VisibleUnits.cpp"
CORE_EXPORT InlineBoxPosition computeInlineBoxPosition(const Position&, TextAffinity);
CORE_EXPORT InlineBoxPosition computeInlineBoxPosition(const Position&, TextAffinity, TextDirection primaryDirection);
CORE_EXPORT InlineBoxPosition computeInlineBoxPosition(const PositionInComposedTree&, TextAffinity);
CORE_EXPORT InlineBoxPosition computeInlineBoxPosition(const PositionInComposedTree&, TextAffinity, TextDirection primaryDirection);
// TODO(yosin) We should move |inRenderedText()| to "VisibleUnits.h" for // TODO(yosin) We should move |inRenderedText()| to "VisibleUnits.h" for
// reduce dependency of |LayoutObject| in |Position| class. // reduce dependency of |LayoutObject| in |Position| class.
CORE_EXPORT bool inRenderedText(const Position&); CORE_EXPORT bool inRenderedText(const Position&);
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include "core/editing/TextAffinity.h" #include "core/editing/TextAffinity.h"
#include "core/editing/VisiblePosition.h" #include "core/editing/VisiblePosition.h"
#include "core/editing/VisibleUnits.h"
#include "core/layout/compositing/CompositedSelectionBound.h" #include "core/layout/compositing/CompositedSelectionBound.h"
#include "core/paint/DeprecatedPaintLayer.h" #include "core/paint/DeprecatedPaintLayer.h"
......
...@@ -138,13 +138,6 @@ private: ...@@ -138,13 +138,6 @@ private:
TextAffinity m_affinity; TextAffinity m_affinity;
}; };
// TODO(yosin) We should move |computeInlineBoxPosition()| to "VisibleUnits.h"
// with |Position| version.
inline InlineBoxPosition computeInlineBoxPosition(const VisiblePosition& position)
{
return computeInlineBoxPosition(position.deepEquivalent(), position.affinity());
}
EphemeralRange makeRange(const VisiblePosition&, const VisiblePosition&); EphemeralRange makeRange(const VisiblePosition&, const VisiblePosition&);
CORE_EXPORT Position canonicalPositionOf(const Position&); CORE_EXPORT Position canonicalPositionOf(const Position&);
......
...@@ -1456,6 +1456,261 @@ VisiblePosition rightBoundaryOfLine(const VisiblePosition& c, TextDirection dire ...@@ -1456,6 +1456,261 @@ VisiblePosition rightBoundaryOfLine(const VisiblePosition& c, TextDirection dire
return direction == LTR ? logicalEndOfLine(c) : logicalStartOfLine(c); return direction == LTR ? logicalEndOfLine(c) : logicalStartOfLine(c);
} }
static bool isNonTextLeafChild(LayoutObject* object)
{
if (object->slowFirstChild())
return false;
if (object->isText())
return false;
return true;
}
static InlineTextBox* searchAheadForBetterMatch(LayoutObject* layoutObject)
{
LayoutBlock* container = layoutObject->containingBlock();
for (LayoutObject* next = layoutObject->nextInPreOrder(container); next; next = next->nextInPreOrder(container)) {
if (next->isLayoutBlock())
return 0;
if (next->isBR())
return 0;
if (isNonTextLeafChild(next))
return 0;
if (next->isText()) {
InlineTextBox* match = 0;
int minOffset = INT_MAX;
for (InlineTextBox* box = toLayoutText(next)->firstTextBox(); box; box = box->nextTextBox()) {
int caretMinOffset = box->caretMinOffset();
if (caretMinOffset < minOffset) {
match = box;
minOffset = caretMinOffset;
}
}
if (match)
return match;
}
}
return 0;
}
template <typename Strategy>
PositionAlgorithm<Strategy> downstreamIgnoringEditingBoundaries(PositionAlgorithm<Strategy> position)
{
PositionAlgorithm<Strategy> lastPosition;
while (position != lastPosition) {
lastPosition = position;
position = position.downstream(CanCrossEditingBoundary);
}
return position;
}
template <typename Strategy>
PositionAlgorithm<Strategy> upstreamIgnoringEditingBoundaries(PositionAlgorithm<Strategy> position)
{
PositionAlgorithm<Strategy> lastPosition;
while (position != lastPosition) {
lastPosition = position;
position = position.upstream(CanCrossEditingBoundary);
}
return position;
}
template <typename Strategy>
static InlineBoxPosition computeInlineBoxPositionAlgorithm(const PositionAlgorithm<Strategy>& position, TextAffinity affinity, TextDirection primaryDirection)
{
InlineBox* inlineBox = nullptr;
int caretOffset = position.computeEditingOffset();
Node* const anchorNode = position.anchorNode();
LayoutObject* layoutObject = anchorNode->isShadowRoot() ? toShadowRoot(anchorNode)->host()->layoutObject() : anchorNode->layoutObject();
if (!layoutObject->isText()) {
inlineBox = 0;
if (canHaveChildrenForEditing(anchorNode) && layoutObject->isLayoutBlockFlow() && hasRenderedNonAnonymousDescendantsWithHeight(layoutObject)) {
// Try a visually equivalent position with possibly opposite
// editability. This helps in case |this| is in an editable block
// but surrounded by non-editable positions. It acts to negate the
// logic at the beginning of LayoutObject::createVisiblePosition().
PositionAlgorithm<Strategy> equivalent = downstreamIgnoringEditingBoundaries(position);
if (equivalent == position) {
equivalent = upstreamIgnoringEditingBoundaries(position);
if (equivalent == position || downstreamIgnoringEditingBoundaries(equivalent) == position)
return InlineBoxPosition(inlineBox, caretOffset);
}
return computeInlineBoxPosition(equivalent, TextAffinity::Upstream, primaryDirection);
}
if (layoutObject->isBox()) {
inlineBox = toLayoutBox(layoutObject)->inlineBoxWrapper();
if (!inlineBox || (caretOffset > inlineBox->caretMinOffset() && caretOffset < inlineBox->caretMaxOffset()))
return InlineBoxPosition(inlineBox, caretOffset);
}
} else {
LayoutText* textLayoutObject = toLayoutText(layoutObject);
InlineTextBox* box;
InlineTextBox* candidate = 0;
for (box = textLayoutObject->firstTextBox(); box; box = box->nextTextBox()) {
int caretMinOffset = box->caretMinOffset();
int caretMaxOffset = box->caretMaxOffset();
if (caretOffset < caretMinOffset || caretOffset > caretMaxOffset || (caretOffset == caretMaxOffset && box->isLineBreak()))
continue;
if (caretOffset > caretMinOffset && caretOffset < caretMaxOffset)
return InlineBoxPosition(box, caretOffset);
if (((caretOffset == caretMaxOffset) ^ (affinity == TextAffinity::Downstream))
|| ((caretOffset == caretMinOffset) ^ (affinity == TextAffinity::Upstream))
|| (caretOffset == caretMaxOffset && box->nextLeafChild() && box->nextLeafChild()->isLineBreak()))
break;
candidate = box;
}
if (candidate && candidate == textLayoutObject->lastTextBox() && affinity == TextAffinity::Downstream) {
box = searchAheadForBetterMatch(textLayoutObject);
if (box)
caretOffset = box->caretMinOffset();
}
inlineBox = box ? box : candidate;
}
if (!inlineBox)
return InlineBoxPosition(inlineBox, caretOffset);
unsigned char level = inlineBox->bidiLevel();
if (inlineBox->direction() == primaryDirection) {
if (caretOffset == inlineBox->caretRightmostOffset()) {
InlineBox* nextBox = inlineBox->nextLeafChild();
if (!nextBox || nextBox->bidiLevel() >= level)
return InlineBoxPosition(inlineBox, caretOffset);
level = nextBox->bidiLevel();
InlineBox* prevBox = inlineBox;
do {
prevBox = prevBox->prevLeafChild();
} while (prevBox && prevBox->bidiLevel() > level);
// For example, abc FED 123 ^ CBA
if (prevBox && prevBox->bidiLevel() == level)
return InlineBoxPosition(inlineBox, caretOffset);
// For example, abc 123 ^ CBA
while (InlineBox* nextBox = inlineBox->nextLeafChild()) {
if (nextBox->bidiLevel() < level)
break;
inlineBox = nextBox;
}
return InlineBoxPosition(inlineBox, inlineBox->caretRightmostOffset());
}
InlineBox* prevBox = inlineBox->prevLeafChild();
if (!prevBox || prevBox->bidiLevel() >= level)
return InlineBoxPosition(inlineBox, caretOffset);
level = prevBox->bidiLevel();
InlineBox* nextBox = inlineBox;
do {
nextBox = nextBox->nextLeafChild();
} while (nextBox && nextBox->bidiLevel() > level);
if (nextBox && nextBox->bidiLevel() == level)
return InlineBoxPosition(inlineBox, caretOffset);
while (InlineBox* prevBox = inlineBox->prevLeafChild()) {
if (prevBox->bidiLevel() < level)
break;
inlineBox = prevBox;
}
return InlineBoxPosition(inlineBox, inlineBox->caretLeftmostOffset());
}
if (caretOffset == inlineBox->caretLeftmostOffset()) {
InlineBox* prevBox = inlineBox->prevLeafChildIgnoringLineBreak();
if (!prevBox || prevBox->bidiLevel() < level) {
// Left edge of a secondary run. Set to the right edge of the entire
// run.
while (InlineBox* nextBox = inlineBox->nextLeafChildIgnoringLineBreak()) {
if (nextBox->bidiLevel() < level)
break;
inlineBox = nextBox;
}
return InlineBoxPosition(inlineBox, inlineBox->caretRightmostOffset());
}
if (prevBox->bidiLevel() > level) {
// Right edge of a "tertiary" run. Set to the left edge of that run.
while (InlineBox* tertiaryBox = inlineBox->prevLeafChildIgnoringLineBreak()) {
if (tertiaryBox->bidiLevel() <= level)
break;
inlineBox = tertiaryBox;
}
return InlineBoxPosition(inlineBox, inlineBox->caretLeftmostOffset());
}
return InlineBoxPosition(inlineBox, caretOffset);
}
if (layoutObject && layoutObject->style()->unicodeBidi() == Plaintext) {
if (inlineBox->bidiLevel() < level)
return InlineBoxPosition(inlineBox, inlineBox->caretLeftmostOffset());
return InlineBoxPosition(inlineBox, inlineBox->caretRightmostOffset());
}
InlineBox* nextBox = inlineBox->nextLeafChildIgnoringLineBreak();
if (!nextBox || nextBox->bidiLevel() < level) {
// Right edge of a secondary run. Set to the left edge of the entire
// run.
while (InlineBox* prevBox = inlineBox->prevLeafChildIgnoringLineBreak()) {
if (prevBox->bidiLevel() < level)
break;
inlineBox = prevBox;
}
return InlineBoxPosition(inlineBox, inlineBox->caretLeftmostOffset());
}
if (nextBox->bidiLevel() <= level)
return InlineBoxPosition(inlineBox, caretOffset);
// Left edge of a "tertiary" run. Set to the right edge of that run.
while (InlineBox* tertiaryBox = inlineBox->nextLeafChildIgnoringLineBreak()) {
if (tertiaryBox->bidiLevel() <= level)
break;
inlineBox = tertiaryBox;
}
return InlineBoxPosition(inlineBox, inlineBox->caretRightmostOffset());
}
template <typename Strategy>
static InlineBoxPosition computeInlineBoxPositionAlgorithm(const PositionAlgorithm<Strategy>& position, TextAffinity affinity)
{
return computeInlineBoxPositionAlgorithm<Strategy>(position, affinity, primaryDirectionOf(*position.anchorNode()));
}
InlineBoxPosition computeInlineBoxPosition(const Position& position, TextAffinity affinity)
{
return computeInlineBoxPositionAlgorithm<EditingStrategy>(position, affinity);
}
InlineBoxPosition computeInlineBoxPosition(const PositionInComposedTree& position, TextAffinity affinity)
{
return computeInlineBoxPositionAlgorithm<EditingInComposedTreeStrategy>(position, affinity);
}
InlineBoxPosition computeInlineBoxPosition(const VisiblePosition& position)
{
return computeInlineBoxPosition(position.deepEquivalent(), position.affinity());
}
InlineBoxPosition computeInlineBoxPosition(const Position& position, TextAffinity affinity, TextDirection primaryDirection)
{
return computeInlineBoxPositionAlgorithm<EditingStrategy>(position, affinity, primaryDirection);
}
InlineBoxPosition computeInlineBoxPosition(const PositionInComposedTree& position, TextAffinity affinity, TextDirection primaryDirection)
{
return computeInlineBoxPositionAlgorithm<EditingInComposedTreeStrategy>(position, affinity, primaryDirection);
}
LayoutRect localCaretRectOfPosition(const PositionWithAffinity& position, LayoutObject*& layoutObject) LayoutRect localCaretRectOfPosition(const PositionWithAffinity& position, LayoutObject*& layoutObject)
{ {
if (position.position().isNull()) { if (position.position().isNull()) {
......
...@@ -39,10 +39,26 @@ class LayoutObject; ...@@ -39,10 +39,26 @@ class LayoutObject;
class Node; class Node;
class VisiblePosition; class VisiblePosition;
class IntPoint; class IntPoint;
class InlineBox;
class LocalFrame; class LocalFrame;
enum EWordSide { RightWordIfOnBoundary = false, LeftWordIfOnBoundary = true }; enum EWordSide { RightWordIfOnBoundary = false, LeftWordIfOnBoundary = true };
struct InlineBoxPosition {
InlineBox* inlineBox;
int offsetInBox;
InlineBoxPosition()
: inlineBox(nullptr), offsetInBox(0)
{
}
InlineBoxPosition(InlineBox* inlineBox, int offsetInBox)
: inlineBox(inlineBox), offsetInBox(offsetInBox)
{
}
};
// Position // Position
// mostForward/BackwardCaretPosition are used for moving back and forth between // mostForward/BackwardCaretPosition are used for moving back and forth between
// visually equivalent candidates. // visually equivalent candidates.
...@@ -126,6 +142,12 @@ VisiblePosition startOfEditableContent(const VisiblePosition&); ...@@ -126,6 +142,12 @@ VisiblePosition startOfEditableContent(const VisiblePosition&);
VisiblePosition endOfEditableContent(const VisiblePosition&); VisiblePosition endOfEditableContent(const VisiblePosition&);
bool isEndOfEditableOrNonEditableContent(const VisiblePosition&); bool isEndOfEditableOrNonEditableContent(const VisiblePosition&);
CORE_EXPORT InlineBoxPosition computeInlineBoxPosition(const Position&, TextAffinity);
CORE_EXPORT InlineBoxPosition computeInlineBoxPosition(const Position&, TextAffinity, TextDirection primaryDirection);
CORE_EXPORT InlineBoxPosition computeInlineBoxPosition(const PositionInComposedTree&, TextAffinity);
CORE_EXPORT InlineBoxPosition computeInlineBoxPosition(const PositionInComposedTree&, TextAffinity, TextDirection primaryDirection);
CORE_EXPORT InlineBoxPosition computeInlineBoxPosition(const VisiblePosition&);
// Rect is local to the returned layoutObject // Rect is local to the returned layoutObject
LayoutRect localCaretRectOfPosition(const PositionWithAffinity&, LayoutObject*&); LayoutRect localCaretRectOfPosition(const PositionWithAffinity&, LayoutObject*&);
bool hasRenderedNonAnonymousDescendantsWithHeight(LayoutObject*); bool hasRenderedNonAnonymousDescendantsWithHeight(LayoutObject*);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment