Index: third_party/WebKit/Source/core/editing/VisibleUnits.cpp |
diff --git a/third_party/WebKit/Source/core/editing/VisibleUnits.cpp b/third_party/WebKit/Source/core/editing/VisibleUnits.cpp |
index 3e2484f8e54e686ead2e863588adec4cfa121e51..674ec43e7e6de1391063bda523020869fc8d9982 100644 |
--- a/third_party/WebKit/Source/core/editing/VisibleUnits.cpp |
+++ b/third_party/WebKit/Source/core/editing/VisibleUnits.cpp |
@@ -165,7 +165,8 @@ PositionInFlatTree CanonicalPositionOf(const PositionInFlatTree& position) { |
} |
template <typename Strategy> |
-static PositionWithAffinityTemplate<Strategy> HonorEditingBoundaryAtOrBefore( |
+static PositionWithAffinityTemplate<Strategy> |
+HonorEditingBoundaryAtOrBeforeTemplate( |
const PositionWithAffinityTemplate<Strategy>& pos, |
const PositionTemplate<Strategy>& anchor) { |
if (pos.IsNull()) |
@@ -198,6 +199,18 @@ static PositionWithAffinityTemplate<Strategy> HonorEditingBoundaryAtOrBefore( |
*highest_root); |
} |
+PositionWithAffinity HonorEditingBoundaryAtOrBefore( |
+ const PositionWithAffinity& pos, |
+ const Position& anchor) { |
+ return HonorEditingBoundaryAtOrBeforeTemplate(pos, anchor); |
+} |
+ |
+PositionInFlatTreeWithAffinity HonorEditingBoundaryAtOrBefore( |
+ const PositionInFlatTreeWithAffinity& pos, |
+ const PositionInFlatTree& anchor) { |
+ return HonorEditingBoundaryAtOrBeforeTemplate(pos, anchor); |
+} |
+ |
template <typename Strategy> |
VisiblePositionTemplate<Strategy> HonorEditingBoundaryAtOrBeforeAlgorithm( |
const VisiblePositionTemplate<Strategy>& pos, |
@@ -220,7 +233,7 @@ VisiblePositionInFlatTree HonorEditingBoundaryAtOrBefore( |
} |
template <typename Strategy> |
-static VisiblePositionTemplate<Strategy> HonorEditingBoundaryAtOrAfter( |
+static VisiblePositionTemplate<Strategy> HonorEditingBoundaryAtOrAfterTemplate( |
const VisiblePositionTemplate<Strategy>& pos, |
const PositionTemplate<Strategy>& anchor) { |
DCHECK(pos.IsValid()) << pos; |
@@ -255,144 +268,15 @@ static VisiblePositionTemplate<Strategy> HonorEditingBoundaryAtOrAfter( |
*highest_root); |
} |
-static bool HasEditableStyle(const Node& node, EditableType editable_type) { |
- if (editable_type == kHasEditableAXRole) { |
- if (AXObjectCache* cache = node.GetDocument().ExistingAXObjectCache()) { |
- if (cache->RootAXEditableElement(&node)) |
- return true; |
- } |
- } |
- |
- return HasEditableStyle(node); |
-} |
- |
-static Element* RootEditableElement(const Node& node, |
- EditableType editable_type) { |
- if (editable_type == kHasEditableAXRole) { |
- if (AXObjectCache* cache = node.GetDocument().ExistingAXObjectCache()) |
- return const_cast<Element*>(cache->RootAXEditableElement(&node)); |
- } |
- |
- return RootEditableElement(node); |
-} |
- |
-static Element* RootAXEditableElementOf(const Position& position) { |
- Node* node = position.ComputeContainerNode(); |
- if (!node) |
- return 0; |
- |
- if (IsDisplayInsideTable(node)) |
- node = node->parentNode(); |
- |
- return RootEditableElement(*node, kHasEditableAXRole); |
-} |
- |
-static bool HasAXEditableStyle(const Node& node) { |
- return HasEditableStyle(node, kHasEditableAXRole); |
-} |
- |
-static ContainerNode* HighestEditableRoot(const Position& position, |
- EditableType editable_type) { |
- if (editable_type == kHasEditableAXRole) |
- return HighestEditableRoot(position, RootAXEditableElementOf, |
- HasAXEditableStyle); |
- |
- return HighestEditableRoot(position); |
-} |
- |
-static Node* PreviousLeafWithSameEditability(Node* node, |
- EditableType editable_type) { |
- bool editable = HasEditableStyle(*node, editable_type); |
- node = PreviousAtomicLeafNode(*node); |
- while (node) { |
- if (editable == HasEditableStyle(*node, editable_type)) |
- return node; |
- node = PreviousAtomicLeafNode(*node); |
- } |
- return 0; |
-} |
- |
-static Node* NextLeafWithSameEditability( |
- Node* node, |
- EditableType editable_type = kContentIsEditable) { |
- if (!node) |
- return 0; |
- |
- bool editable = HasEditableStyle(*node, editable_type); |
- node = NextAtomicLeafNode(*node); |
- while (node) { |
- if (editable == HasEditableStyle(*node, editable_type)) |
- return node; |
- node = NextAtomicLeafNode(*node); |
- } |
- return 0; |
-} |
- |
-// FIXME: consolidate with code in previousLinePosition. |
-Position PreviousRootInlineBoxCandidatePosition( |
- Node* node, |
- const VisiblePosition& visible_position, |
- EditableType editable_type) { |
- DCHECK(visible_position.IsValid()) << visible_position; |
- ContainerNode* highest_root = |
- HighestEditableRoot(visible_position.DeepEquivalent(), editable_type); |
- Node* previous_node = PreviousLeafWithSameEditability(node, editable_type); |
- |
- while (previous_node && |
- (!previous_node->GetLayoutObject() || |
- InSameLine( |
- CreateVisiblePosition(FirstPositionInOrBeforeNode(previous_node)), |
- visible_position))) |
- previous_node = |
- PreviousLeafWithSameEditability(previous_node, editable_type); |
- |
- while (previous_node && !previous_node->IsShadowRoot()) { |
- if (HighestEditableRoot(FirstPositionInOrBeforeNode(previous_node), |
- editable_type) != highest_root) |
- break; |
- |
- Position pos = isHTMLBRElement(*previous_node) |
- ? Position::BeforeNode(previous_node) |
- : Position::EditingPositionOf( |
- previous_node, CaretMaxOffset(previous_node)); |
- |
- if (IsVisuallyEquivalentCandidate(pos)) |
- return pos; |
- |
- previous_node = |
- PreviousLeafWithSameEditability(previous_node, editable_type); |
- } |
- return Position(); |
+VisiblePosition HonorEditingBoundaryAtOrAfter(const VisiblePosition& pos, |
+ const Position& anchor) { |
+ return HonorEditingBoundaryAtOrAfterTemplate(pos, anchor); |
} |
-Position NextRootInlineBoxCandidatePosition( |
- Node* node, |
- const VisiblePosition& visible_position, |
- EditableType editable_type) { |
- DCHECK(visible_position.IsValid()) << visible_position; |
- ContainerNode* highest_root = |
- HighestEditableRoot(visible_position.DeepEquivalent(), editable_type); |
- Node* next_node = NextLeafWithSameEditability(node, editable_type); |
- while (next_node && (!next_node->GetLayoutObject() || |
- InSameLine(CreateVisiblePosition( |
- FirstPositionInOrBeforeNode(next_node)), |
- visible_position))) |
- next_node = NextLeafWithSameEditability(next_node, kContentIsEditable); |
- |
- while (next_node && !next_node->IsShadowRoot()) { |
- if (HighestEditableRoot(FirstPositionInOrBeforeNode(next_node), |
- editable_type) != highest_root) |
- break; |
- |
- Position pos; |
- pos = Position::EditingPositionOf(next_node, CaretMinOffset(next_node)); |
- |
- if (IsVisuallyEquivalentCandidate(pos)) |
- return pos; |
- |
- next_node = NextLeafWithSameEditability(next_node, editable_type); |
- } |
- return Position(); |
+VisiblePositionInFlatTree HonorEditingBoundaryAtOrAfter( |
+ const VisiblePositionInFlatTree& pos, |
+ const PositionInFlatTree& anchor) { |
+ return HonorEditingBoundaryAtOrAfterTemplate(pos, anchor); |
} |
template <typename Strategy> |
@@ -809,509 +693,6 @@ VisiblePosition NextWordPosition(const VisiblePosition& c) { |
// --------- |
-enum LineEndpointComputationMode { kUseLogicalOrdering, kUseInlineBoxOrdering }; |
-template <typename Strategy> |
-static PositionWithAffinityTemplate<Strategy> StartPositionForLine( |
- const PositionWithAffinityTemplate<Strategy>& c, |
- LineEndpointComputationMode mode) { |
- if (c.IsNull()) |
- return PositionWithAffinityTemplate<Strategy>(); |
- |
- RootInlineBox* root_box = |
- RenderedPosition(c.GetPosition(), c.Affinity()).RootBox(); |
- if (!root_box) { |
- // There are VisiblePositions at offset 0 in blocks without |
- // RootInlineBoxes, like empty editable blocks and bordered blocks. |
- PositionTemplate<Strategy> p = c.GetPosition(); |
- if (p.AnchorNode()->GetLayoutObject() && |
- p.AnchorNode()->GetLayoutObject()->IsLayoutBlock() && |
- !p.ComputeEditingOffset()) |
- return c; |
- |
- return PositionWithAffinityTemplate<Strategy>(); |
- } |
- |
- Node* start_node; |
- InlineBox* start_box; |
- if (mode == kUseLogicalOrdering) { |
- start_node = root_box->GetLogicalStartBoxWithNode(start_box); |
- if (!start_node) |
- return PositionWithAffinityTemplate<Strategy>(); |
- } else { |
- // Generated content (e.g. list markers and CSS :before and :after |
- // pseudoelements) have no corresponding DOM element, and so cannot be |
- // represented by a VisiblePosition. Use whatever follows instead. |
- start_box = root_box->FirstLeafChild(); |
- while (true) { |
- if (!start_box) |
- return PositionWithAffinityTemplate<Strategy>(); |
- |
- start_node = start_box->GetLineLayoutItem().NonPseudoNode(); |
- if (start_node) |
- break; |
- |
- start_box = start_box->NextLeafChild(); |
- } |
- } |
- |
- return PositionWithAffinityTemplate<Strategy>( |
- start_node->IsTextNode() |
- ? PositionTemplate<Strategy>(ToText(start_node), |
- ToInlineTextBox(start_box)->Start()) |
- : PositionTemplate<Strategy>::BeforeNode(start_node)); |
-} |
- |
-template <typename Strategy> |
-static PositionWithAffinityTemplate<Strategy> StartOfLineAlgorithm( |
- const PositionWithAffinityTemplate<Strategy>& c) { |
- // TODO: this is the current behavior that might need to be fixed. |
- // Please refer to https://bugs.webkit.org/show_bug.cgi?id=49107 for detail. |
- PositionWithAffinityTemplate<Strategy> vis_pos = |
- StartPositionForLine(c, kUseInlineBoxOrdering); |
- return HonorEditingBoundaryAtOrBefore(vis_pos, c.GetPosition()); |
-} |
- |
-static PositionWithAffinity StartOfLine( |
- const PositionWithAffinity& current_position) { |
- return StartOfLineAlgorithm<EditingStrategy>(current_position); |
-} |
- |
-static PositionInFlatTreeWithAffinity StartOfLine( |
- const PositionInFlatTreeWithAffinity& current_position) { |
- return StartOfLineAlgorithm<EditingInFlatTreeStrategy>(current_position); |
-} |
- |
-// FIXME: Rename this function to reflect the fact it ignores bidi levels. |
-VisiblePosition StartOfLine(const VisiblePosition& current_position) { |
- DCHECK(current_position.IsValid()) << current_position; |
- return CreateVisiblePosition( |
- StartOfLine(current_position.ToPositionWithAffinity())); |
-} |
- |
-VisiblePositionInFlatTree StartOfLine( |
- const VisiblePositionInFlatTree& current_position) { |
- DCHECK(current_position.IsValid()) << current_position; |
- return CreateVisiblePosition( |
- StartOfLine(current_position.ToPositionWithAffinity())); |
-} |
- |
-template <typename Strategy> |
-static PositionWithAffinityTemplate<Strategy> LogicalStartOfLineAlgorithm( |
- const PositionWithAffinityTemplate<Strategy>& c) { |
- // TODO: this is the current behavior that might need to be fixed. |
- // Please refer to https://bugs.webkit.org/show_bug.cgi?id=49107 for detail. |
- PositionWithAffinityTemplate<Strategy> vis_pos = |
- StartPositionForLine(c, kUseLogicalOrdering); |
- |
- if (ContainerNode* editable_root = HighestEditableRoot(c.GetPosition())) { |
- if (!editable_root->contains(vis_pos.GetPosition().ComputeContainerNode())) |
- return PositionWithAffinityTemplate<Strategy>( |
- PositionTemplate<Strategy>::FirstPositionInNode(editable_root)); |
- } |
- |
- return HonorEditingBoundaryAtOrBefore(vis_pos, c.GetPosition()); |
-} |
- |
-VisiblePosition LogicalStartOfLine(const VisiblePosition& current_position) { |
- DCHECK(current_position.IsValid()) << current_position; |
- return CreateVisiblePosition(LogicalStartOfLineAlgorithm<EditingStrategy>( |
- current_position.ToPositionWithAffinity())); |
-} |
- |
-VisiblePositionInFlatTree LogicalStartOfLine( |
- const VisiblePositionInFlatTree& current_position) { |
- DCHECK(current_position.IsValid()) << current_position; |
- return CreateVisiblePosition( |
- LogicalStartOfLineAlgorithm<EditingInFlatTreeStrategy>( |
- current_position.ToPositionWithAffinity())); |
-} |
- |
-template <typename Strategy> |
-static VisiblePositionTemplate<Strategy> EndPositionForLine( |
- const VisiblePositionTemplate<Strategy>& c, |
- LineEndpointComputationMode mode) { |
- DCHECK(c.IsValid()) << c; |
- if (c.IsNull()) |
- return VisiblePositionTemplate<Strategy>(); |
- |
- RootInlineBox* root_box = RenderedPosition(c).RootBox(); |
- if (!root_box) { |
- // There are VisiblePositions at offset 0 in blocks without |
- // RootInlineBoxes, like empty editable blocks and bordered blocks. |
- const PositionTemplate<Strategy> p = c.DeepEquivalent(); |
- if (p.AnchorNode()->GetLayoutObject() && |
- p.AnchorNode()->GetLayoutObject()->IsLayoutBlock() && |
- !p.ComputeEditingOffset()) |
- return c; |
- return VisiblePositionTemplate<Strategy>(); |
- } |
- |
- Node* end_node; |
- InlineBox* end_box; |
- if (mode == kUseLogicalOrdering) { |
- end_node = root_box->GetLogicalEndBoxWithNode(end_box); |
- if (!end_node) |
- return VisiblePositionTemplate<Strategy>(); |
- } else { |
- // Generated content (e.g. list markers and CSS :before and :after |
- // pseudo elements) have no corresponding DOM element, and so cannot be |
- // represented by a VisiblePosition. Use whatever precedes instead. |
- end_box = root_box->LastLeafChild(); |
- while (true) { |
- if (!end_box) |
- return VisiblePositionTemplate<Strategy>(); |
- |
- end_node = end_box->GetLineLayoutItem().NonPseudoNode(); |
- if (end_node) |
- break; |
- |
- end_box = end_box->PrevLeafChild(); |
- } |
- } |
- |
- PositionTemplate<Strategy> pos; |
- if (isHTMLBRElement(*end_node)) { |
- pos = PositionTemplate<Strategy>::BeforeNode(end_node); |
- } else if (end_box->IsInlineTextBox() && end_node->IsTextNode()) { |
- InlineTextBox* end_text_box = ToInlineTextBox(end_box); |
- int end_offset = end_text_box->Start(); |
- if (!end_text_box->IsLineBreak()) |
- end_offset += end_text_box->Len(); |
- pos = PositionTemplate<Strategy>(ToText(end_node), end_offset); |
- } else { |
- pos = PositionTemplate<Strategy>::AfterNode(end_node); |
- } |
- |
- return CreateVisiblePosition(pos, VP_UPSTREAM_IF_POSSIBLE); |
-} |
- |
-// TODO(yosin) Rename this function to reflect the fact it ignores bidi levels. |
-template <typename Strategy> |
-static VisiblePositionTemplate<Strategy> EndOfLineAlgorithm( |
- const VisiblePositionTemplate<Strategy>& current_position) { |
- DCHECK(current_position.IsValid()) << current_position; |
- // TODO(yosin) this is the current behavior that might need to be fixed. |
- // Please refer to https://bugs.webkit.org/show_bug.cgi?id=49107 for detail. |
- VisiblePositionTemplate<Strategy> vis_pos = |
- EndPositionForLine(current_position, kUseInlineBoxOrdering); |
- |
- // Make sure the end of line is at the same line as the given input |
- // position. Else use the previous position to obtain end of line. This |
- // condition happens when the input position is before the space character |
- // at the end of a soft-wrapped non-editable line. In this scenario, |
- // |endPositionForLine()| would incorrectly hand back a position in the next |
- // line instead. This fix is to account for the discrepancy between lines |
- // with "webkit-line-break:after-white-space" style versus lines without |
- // that style, which would break before a space by default. |
- if (!InSameLine(current_position, vis_pos)) { |
- vis_pos = PreviousPositionOf(current_position); |
- if (vis_pos.IsNull()) |
- return VisiblePositionTemplate<Strategy>(); |
- vis_pos = EndPositionForLine(vis_pos, kUseInlineBoxOrdering); |
- } |
- |
- return HonorEditingBoundaryAtOrAfter(vis_pos, |
- current_position.DeepEquivalent()); |
-} |
- |
-// TODO(yosin) Rename this function to reflect the fact it ignores bidi levels. |
-VisiblePosition EndOfLine(const VisiblePosition& current_position) { |
- return EndOfLineAlgorithm<EditingStrategy>(current_position); |
-} |
- |
-VisiblePositionInFlatTree EndOfLine( |
- const VisiblePositionInFlatTree& current_position) { |
- return EndOfLineAlgorithm<EditingInFlatTreeStrategy>(current_position); |
-} |
- |
-template <typename Strategy> |
-static bool InSameLogicalLine(const VisiblePositionTemplate<Strategy>& a, |
- const VisiblePositionTemplate<Strategy>& b) { |
- DCHECK(a.IsValid()) << a; |
- DCHECK(b.IsValid()) << b; |
- return a.IsNotNull() && LogicalStartOfLine(a).DeepEquivalent() == |
- LogicalStartOfLine(b).DeepEquivalent(); |
-} |
- |
-template <typename Strategy> |
-VisiblePositionTemplate<Strategy> LogicalEndOfLineAlgorithm( |
- const VisiblePositionTemplate<Strategy>& current_position) { |
- DCHECK(current_position.IsValid()) << current_position; |
- // TODO(yosin) this is the current behavior that might need to be fixed. |
- // Please refer to https://bugs.webkit.org/show_bug.cgi?id=49107 for detail. |
- VisiblePositionTemplate<Strategy> vis_pos = |
- EndPositionForLine(current_position, kUseLogicalOrdering); |
- |
- // Make sure the end of line is at the same line as the given input |
- // position. For a wrapping line, the logical end position for the |
- // not-last-2-lines might incorrectly hand back the logical beginning of the |
- // next line. For example, |
- // <div contenteditable dir="rtl" style="line-break:before-white-space">xyz |
- // a xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz </div> |
- // In this case, use the previous position of the computed logical end |
- // position. |
- if (!InSameLogicalLine(current_position, vis_pos)) |
- vis_pos = PreviousPositionOf(vis_pos); |
- |
- if (ContainerNode* editable_root = |
- HighestEditableRoot(current_position.DeepEquivalent())) { |
- if (!editable_root->contains( |
- vis_pos.DeepEquivalent().ComputeContainerNode())) |
- return CreateVisiblePosition( |
- PositionTemplate<Strategy>::LastPositionInNode(editable_root)); |
- } |
- |
- return HonorEditingBoundaryAtOrAfter(vis_pos, |
- current_position.DeepEquivalent()); |
-} |
- |
-VisiblePosition LogicalEndOfLine(const VisiblePosition& current_position) { |
- return LogicalEndOfLineAlgorithm<EditingStrategy>(current_position); |
-} |
- |
-VisiblePositionInFlatTree LogicalEndOfLine( |
- const VisiblePositionInFlatTree& current_position) { |
- return LogicalEndOfLineAlgorithm<EditingInFlatTreeStrategy>(current_position); |
-} |
- |
-template <typename Strategy> |
-bool InSameLineAlgorithm( |
- const PositionWithAffinityTemplate<Strategy>& position1, |
- const PositionWithAffinityTemplate<Strategy>& position2) { |
- if (position1.IsNull() || position2.IsNull()) |
- return false; |
- DCHECK_EQ(position1.GetDocument(), position2.GetDocument()); |
- DCHECK(!position1.GetDocument()->NeedsLayoutTreeUpdate()); |
- |
- PositionWithAffinityTemplate<Strategy> start_of_line1 = |
- StartOfLine(position1); |
- PositionWithAffinityTemplate<Strategy> start_of_line2 = |
- StartOfLine(position2); |
- if (start_of_line1 == start_of_line2) |
- return true; |
- PositionTemplate<Strategy> canonicalized1 = |
- CanonicalPositionOf(start_of_line1.GetPosition()); |
- if (canonicalized1 == start_of_line2.GetPosition()) |
- return true; |
- return canonicalized1 == CanonicalPositionOf(start_of_line2.GetPosition()); |
-} |
- |
-bool InSameLine(const PositionWithAffinity& a, const PositionWithAffinity& b) { |
- return InSameLineAlgorithm<EditingStrategy>(a, b); |
-} |
- |
-bool InSameLine(const PositionInFlatTreeWithAffinity& position1, |
- const PositionInFlatTreeWithAffinity& position2) { |
- return InSameLineAlgorithm<EditingInFlatTreeStrategy>(position1, position2); |
-} |
- |
-bool InSameLine(const VisiblePosition& position1, |
- const VisiblePosition& position2) { |
- DCHECK(position1.IsValid()) << position1; |
- DCHECK(position2.IsValid()) << position2; |
- return InSameLine(position1.ToPositionWithAffinity(), |
- position2.ToPositionWithAffinity()); |
-} |
- |
-bool InSameLine(const VisiblePositionInFlatTree& position1, |
- const VisiblePositionInFlatTree& position2) { |
- DCHECK(position1.IsValid()) << position1; |
- DCHECK(position2.IsValid()) << position2; |
- return InSameLine(position1.ToPositionWithAffinity(), |
- position2.ToPositionWithAffinity()); |
-} |
- |
-template <typename Strategy> |
-bool IsStartOfLineAlgorithm(const VisiblePositionTemplate<Strategy>& p) { |
- DCHECK(p.IsValid()) << p; |
- return p.IsNotNull() && p.DeepEquivalent() == StartOfLine(p).DeepEquivalent(); |
-} |
- |
-bool IsStartOfLine(const VisiblePosition& p) { |
- return IsStartOfLineAlgorithm<EditingStrategy>(p); |
-} |
- |
-bool IsStartOfLine(const VisiblePositionInFlatTree& p) { |
- return IsStartOfLineAlgorithm<EditingInFlatTreeStrategy>(p); |
-} |
- |
-template <typename Strategy> |
-bool IsEndOfLineAlgorithm(const VisiblePositionTemplate<Strategy>& p) { |
- DCHECK(p.IsValid()) << p; |
- return p.IsNotNull() && p.DeepEquivalent() == EndOfLine(p).DeepEquivalent(); |
-} |
- |
-bool IsEndOfLine(const VisiblePosition& p) { |
- return IsEndOfLineAlgorithm<EditingStrategy>(p); |
-} |
- |
-bool IsEndOfLine(const VisiblePositionInFlatTree& p) { |
- return IsEndOfLineAlgorithm<EditingInFlatTreeStrategy>(p); |
-} |
- |
-template <typename Strategy> |
-static bool IsLogicalEndOfLineAlgorithm( |
- const VisiblePositionTemplate<Strategy>& p) { |
- DCHECK(p.IsValid()) << p; |
- return p.IsNotNull() && |
- p.DeepEquivalent() == LogicalEndOfLine(p).DeepEquivalent(); |
-} |
- |
-bool IsLogicalEndOfLine(const VisiblePosition& p) { |
- return IsLogicalEndOfLineAlgorithm<EditingStrategy>(p); |
-} |
- |
-bool IsLogicalEndOfLine(const VisiblePositionInFlatTree& p) { |
- return IsLogicalEndOfLineAlgorithm<EditingInFlatTreeStrategy>(p); |
-} |
- |
-static inline LayoutPoint AbsoluteLineDirectionPointToLocalPointInBlock( |
- RootInlineBox* root, |
- LayoutUnit line_direction_point) { |
- DCHECK(root); |
- LineLayoutBlockFlow containing_block = root->Block(); |
- FloatPoint absolute_block_point = |
- containing_block.LocalToAbsolute(FloatPoint()); |
- if (containing_block.HasOverflowClip()) |
- absolute_block_point -= FloatSize(containing_block.ScrolledContentOffset()); |
- |
- if (root->Block().IsHorizontalWritingMode()) |
- return LayoutPoint( |
- LayoutUnit(line_direction_point - absolute_block_point.X()), |
- root->BlockDirectionPointInLine()); |
- |
- return LayoutPoint( |
- root->BlockDirectionPointInLine(), |
- LayoutUnit(line_direction_point - absolute_block_point.Y())); |
-} |
- |
-VisiblePosition PreviousLinePosition(const VisiblePosition& visible_position, |
- LayoutUnit line_direction_point, |
- EditableType editable_type) { |
- DCHECK(visible_position.IsValid()) << visible_position; |
- |
- Position p = visible_position.DeepEquivalent(); |
- Node* node = p.AnchorNode(); |
- |
- if (!node) |
- return VisiblePosition(); |
- |
- LayoutObject* layout_object = node->GetLayoutObject(); |
- if (!layout_object) |
- return VisiblePosition(); |
- |
- RootInlineBox* root = 0; |
- InlineBox* box = ComputeInlineBoxPosition(visible_position).inline_box; |
- if (box) { |
- root = box->Root().PrevRootBox(); |
- // We want to skip zero height boxes. |
- // This could happen in case it is a TrailingFloatsRootInlineBox. |
- if (!root || !root->LogicalHeight() || !root->FirstLeafChild()) |
- root = 0; |
- } |
- |
- if (!root) { |
- Position position = PreviousRootInlineBoxCandidatePosition( |
- node, visible_position, editable_type); |
- if (position.IsNotNull()) { |
- RenderedPosition rendered_position((CreateVisiblePosition(position))); |
- root = rendered_position.RootBox(); |
- if (!root) |
- return CreateVisiblePosition(position); |
- } |
- } |
- |
- if (root) { |
- // FIXME: Can be wrong for multi-column layout and with transforms. |
- LayoutPoint point_in_line = AbsoluteLineDirectionPointToLocalPointInBlock( |
- root, line_direction_point); |
- LineLayoutItem line_layout_item = |
- root->ClosestLeafChildForPoint(point_in_line, IsEditablePosition(p)) |
- ->GetLineLayoutItem(); |
- Node* node = line_layout_item.GetNode(); |
- if (node && EditingIgnoresContent(*node)) |
- return VisiblePosition::InParentBeforeNode(*node); |
- return CreateVisiblePosition( |
- line_layout_item.PositionForPoint(point_in_line)); |
- } |
- |
- // Could not find a previous line. This means we must already be on the first |
- // line. Move to the start of the content in this block, which effectively |
- // moves us to the start of the line we're on. |
- Element* root_element = HasEditableStyle(*node, editable_type) |
- ? RootEditableElement(*node, editable_type) |
- : node->GetDocument().documentElement(); |
- if (!root_element) |
- return VisiblePosition(); |
- return VisiblePosition::FirstPositionInNode(root_element); |
-} |
- |
-VisiblePosition NextLinePosition(const VisiblePosition& visible_position, |
- LayoutUnit line_direction_point, |
- EditableType editable_type) { |
- DCHECK(visible_position.IsValid()) << visible_position; |
- |
- Position p = visible_position.DeepEquivalent(); |
- Node* node = p.AnchorNode(); |
- |
- if (!node) |
- return VisiblePosition(); |
- |
- LayoutObject* layout_object = node->GetLayoutObject(); |
- if (!layout_object) |
- return VisiblePosition(); |
- |
- RootInlineBox* root = 0; |
- InlineBox* box = ComputeInlineBoxPosition(visible_position).inline_box; |
- if (box) { |
- root = box->Root().NextRootBox(); |
- // We want to skip zero height boxes. |
- // This could happen in case it is a TrailingFloatsRootInlineBox. |
- if (!root || !root->LogicalHeight() || !root->FirstLeafChild()) |
- root = 0; |
- } |
- |
- if (!root) { |
- // FIXME: We need do the same in previousLinePosition. |
- Node* child = NodeTraversal::ChildAt(*node, p.ComputeEditingOffset()); |
- node = child ? child : &NodeTraversal::LastWithinOrSelf(*node); |
- Position position = NextRootInlineBoxCandidatePosition( |
- node, visible_position, editable_type); |
- if (position.IsNotNull()) { |
- RenderedPosition rendered_position((CreateVisiblePosition(position))); |
- root = rendered_position.RootBox(); |
- if (!root) |
- return CreateVisiblePosition(position); |
- } |
- } |
- |
- if (root) { |
- // FIXME: Can be wrong for multi-column layout and with transforms. |
- LayoutPoint point_in_line = AbsoluteLineDirectionPointToLocalPointInBlock( |
- root, line_direction_point); |
- LineLayoutItem line_layout_item = |
- root->ClosestLeafChildForPoint(point_in_line, IsEditablePosition(p)) |
- ->GetLineLayoutItem(); |
- Node* node = line_layout_item.GetNode(); |
- if (node && EditingIgnoresContent(*node)) |
- return VisiblePosition::InParentBeforeNode(*node); |
- return CreateVisiblePosition( |
- line_layout_item.PositionForPoint(point_in_line)); |
- } |
- |
- // Could not find a next line. This means we must already be on the last line. |
- // Move to the end of the content in this block, which effectively moves us |
- // to the end of the line we're on. |
- Element* root_element = HasEditableStyle(*node, editable_type) |
- ? RootEditableElement(*node, editable_type) |
- : node->GetDocument().documentElement(); |
- if (!root_element) |
- return VisiblePosition(); |
- return VisiblePosition::LastPositionInNode(root_element); |
-} |
- |
-// --------- |
- |
static unsigned StartSentenceBoundary(const UChar* characters, |
unsigned length, |
unsigned, |