/*
 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "core/editing/VisibleUnits.h"

#include "core/HTMLNames.h"
#include "core/dom/Document.h"
#include "core/dom/Element.h"
#include "core/dom/FirstLetterPseudoElement.h"
#include "core/dom/NodeTraversal.h"
#include "core/dom/Text.h"
#include "core/editing/EditingUtilities.h"
#include "core/editing/FrameSelection.h"
#include "core/editing/Position.h"
#include "core/editing/PositionIterator.h"
#include "core/editing/RenderedPosition.h"
#include "core/editing/TextAffinity.h"
#include "core/editing/VisiblePosition.h"
#include "core/editing/iterators/BackwardsCharacterIterator.h"
#include "core/editing/iterators/BackwardsTextBuffer.h"
#include "core/editing/iterators/CharacterIterator.h"
#include "core/editing/iterators/ForwardsTextBuffer.h"
#include "core/editing/iterators/SimplifiedBackwardsTextIterator.h"
#include "core/editing/iterators/TextIterator.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/Settings.h"
#include "core/html/HTMLBRElement.h"
#include "core/html/TextControlElement.h"
#include "core/layout/HitTestRequest.h"
#include "core/layout/HitTestResult.h"
#include "core/layout/LayoutInline.h"
#include "core/layout/LayoutObject.h"
#include "core/layout/LayoutTextFragment.h"
#include "core/layout/LayoutView.h"
#include "core/layout/api/LayoutItem.h"
#include "core/layout/api/LayoutViewItem.h"
#include "core/layout/api/LineLayoutAPIShim.h"
#include "core/layout/api/LineLayoutItem.h"
#include "core/layout/line/InlineIterator.h"
#include "core/layout/line/InlineTextBox.h"
#include "platform/heap/Handle.h"
#include "platform/text/TextBoundaries.h"
#include "platform/text/TextBreakIterator.h"

namespace blink {

template <typename PositionType>
static PositionType CanonicalizeCandidate(const PositionType& candidate) {
  if (candidate.IsNull())
    return PositionType();
  DCHECK(IsVisuallyEquivalentCandidate(candidate));
  PositionType upstream = MostBackwardCaretPosition(candidate);
  if (IsVisuallyEquivalentCandidate(upstream))
    return upstream;
  return candidate;
}

template <typename PositionType>
static PositionType CanonicalPosition(const PositionType& position) {
  // Sometimes updating selection positions can be extremely expensive and
  // occur frequently.  Often calling preventDefault on mousedown events can
  // avoid doing unnecessary text selection work.  http://crbug.com/472258.
  TRACE_EVENT0("input", "VisibleUnits::canonicalPosition");

  // FIXME (9535):  Canonicalizing to the leftmost candidate means that if
  // we're at a line wrap, we will ask layoutObjects to paint downstream
  // carets for other layoutObjects. To fix this, we need to either a) add
  // code to all paintCarets to pass the responsibility off to the appropriate
  // layoutObject for VisiblePosition's like these, or b) canonicalize to the
  // rightmost candidate unless the affinity is upstream.
  if (position.IsNull())
    return PositionType();

  DCHECK(position.GetDocument());
  DCHECK(!position.GetDocument()->NeedsLayoutTreeUpdate());

  const PositionType& backward_candidate = MostBackwardCaretPosition(position);
  if (IsVisuallyEquivalentCandidate(backward_candidate))
    return backward_candidate;

  const PositionType& forward_candidate = MostForwardCaretPosition(position);
  if (IsVisuallyEquivalentCandidate(forward_candidate))
    return forward_candidate;

  // When neither upstream or downstream gets us to a candidate
  // (upstream/downstream won't leave blocks or enter new ones), we search
  // forward and backward until we find one.
  const PositionType& next = CanonicalizeCandidate(NextCandidate(position));
  const PositionType& prev = CanonicalizeCandidate(PreviousCandidate(position));

  // The new position must be in the same editable element. Enforce that
  // first. Unless the descent is from a non-editable html element to an
  // editable body.
  Node* const node = position.ComputeContainerNode();
  if (node && node->GetDocument().documentElement() == node &&
      !HasEditableStyle(*node) && node->GetDocument().body() &&
      HasEditableStyle(*node->GetDocument().body()))
    return next.IsNotNull() ? next : prev;

  Element* const editing_root = RootEditableElementOf(position);
  // If the html element is editable, descending into its body will look like
  // a descent from non-editable to editable content since
  // |rootEditableElementOf()| always stops at the body.
  if ((editing_root &&
       editing_root->GetDocument().documentElement() == editing_root) ||
      position.AnchorNode()->IsDocumentNode())
    return next.IsNotNull() ? next : prev;

  Node* const next_node = next.AnchorNode();
  Node* const prev_node = prev.AnchorNode();
  const bool prev_is_in_same_editable_element =
      prev_node && RootEditableElementOf(prev) == editing_root;
  const bool next_is_in_same_editable_element =
      next_node && RootEditableElementOf(next) == editing_root;
  if (prev_is_in_same_editable_element && !next_is_in_same_editable_element)
    return prev;

  if (next_is_in_same_editable_element && !prev_is_in_same_editable_element)
    return next;

  if (!next_is_in_same_editable_element && !prev_is_in_same_editable_element)
    return PositionType();

  // The new position should be in the same block flow element. Favor that.
  Element* const original_block = node ? EnclosingBlockFlowElement(*node) : 0;
  const bool next_is_outside_original_block =
      !next_node->IsDescendantOf(original_block) && next_node != original_block;
  const bool prev_is_outside_original_block =
      !prev_node->IsDescendantOf(original_block) && prev_node != original_block;
  if (next_is_outside_original_block && !prev_is_outside_original_block)
    return prev;

  return next;
}

Position CanonicalPositionOf(const Position& position) {
  return CanonicalPosition(position);
}

PositionInFlatTree CanonicalPositionOf(const PositionInFlatTree& position) {
  return CanonicalPosition(position);
}

template <typename Strategy>
static PositionWithAffinityTemplate<Strategy> HonorEditingBoundaryAtOrBefore(
    const PositionWithAffinityTemplate<Strategy>& pos,
    const PositionTemplate<Strategy>& anchor) {
  if (pos.IsNull())
    return pos;

  ContainerNode* highest_root = HighestEditableRoot(anchor);

  // Return empty position if |pos| is not somewhere inside the editable
  // region containing this position
  if (highest_root && !pos.AnchorNode()->IsDescendantOf(highest_root))
    return PositionWithAffinityTemplate<Strategy>();

  // Return |pos| itself if the two are from the very same editable region, or
  // both are non-editable
  // TODO(yosin) In the non-editable case, just because the new position is
  // non-editable doesn't mean movement to it is allowed.
  // |VisibleSelection::adjustForEditableContent()| has this problem too.
  if (HighestEditableRoot(pos.GetPosition()) == highest_root)
    return pos;

  // Return empty position if this position is non-editable, but |pos| is
  // editable.
  // TODO(yosin) Move to the previous non-editable region.
  if (!highest_root)
    return PositionWithAffinityTemplate<Strategy>();

  // Return the last position before |pos| that is in the same editable region
  // as this position
  return LastEditablePositionBeforePositionInRoot(pos.GetPosition(),
                                                  *highest_root);
}

template <typename Strategy>
static VisiblePositionTemplate<Strategy> HonorEditingBoundaryAtOrBefore(
    const VisiblePositionTemplate<Strategy>& pos,
    const PositionTemplate<Strategy>& anchor) {
  DCHECK(pos.IsValid()) << pos;
  return CreateVisiblePosition(
      HonorEditingBoundaryAtOrBefore(pos.ToPositionWithAffinity(), anchor));
}

template <typename Strategy>
static VisiblePositionTemplate<Strategy> HonorEditingBoundaryAtOrAfter(
    const VisiblePositionTemplate<Strategy>& pos,
    const PositionTemplate<Strategy>& anchor) {
  DCHECK(pos.IsValid()) << pos;
  if (pos.IsNull())
    return pos;

  ContainerNode* highest_root = HighestEditableRoot(anchor);

  // Return empty position if |pos| is not somewhere inside the editable
  // region containing this position
  if (highest_root &&
      !pos.DeepEquivalent().AnchorNode()->IsDescendantOf(highest_root))
    return VisiblePositionTemplate<Strategy>();

  // Return |pos| itself if the two are from the very same editable region, or
  // both are non-editable
  // TODO(yosin) In the non-editable case, just because the new position is
  // non-editable doesn't mean movement to it is allowed.
  // |VisibleSelection::adjustForEditableContent()| has this problem too.
  if (HighestEditableRoot(pos.DeepEquivalent()) == highest_root)
    return pos;

  // Return empty position if this position is non-editable, but |pos| is
  // editable.
  // TODO(yosin) Move to the next non-editable region.
  if (!highest_root)
    return VisiblePositionTemplate<Strategy>();

  // Return the next position after |pos| that is in the same editable region
  // as this position
  return FirstEditableVisiblePositionAfterPositionInRoot(pos.DeepEquivalent(),
                                                         *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.
static 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();
}

static 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();
}

class CachedLogicallyOrderedLeafBoxes {
 public:
  CachedLogicallyOrderedLeafBoxes();

  const InlineTextBox* PreviousTextBox(const RootInlineBox*,
                                       const InlineTextBox*);
  const InlineTextBox* NextTextBox(const RootInlineBox*, const InlineTextBox*);

  size_t size() const { return leaf_boxes_.size(); }
  const InlineBox* FirstBox() const { return leaf_boxes_[0]; }

 private:
  const Vector<InlineBox*>& CollectBoxes(const RootInlineBox*);
  int BoxIndexInLeaves(const InlineTextBox*) const;

  const RootInlineBox* root_inline_box_;
  Vector<InlineBox*> leaf_boxes_;
};

CachedLogicallyOrderedLeafBoxes::CachedLogicallyOrderedLeafBoxes()
    : root_inline_box_(0) {}

const InlineTextBox* CachedLogicallyOrderedLeafBoxes::PreviousTextBox(
    const RootInlineBox* root,
    const InlineTextBox* box) {
  if (!root)
    return 0;

  CollectBoxes(root);

  // If box is null, root is box's previous RootInlineBox, and previousBox is
  // the last logical box in root.
  int box_index = leaf_boxes_.size() - 1;
  if (box)
    box_index = BoxIndexInLeaves(box) - 1;

  for (int i = box_index; i >= 0; --i) {
    if (leaf_boxes_[i]->IsInlineTextBox())
      return ToInlineTextBox(leaf_boxes_[i]);
  }

  return 0;
}

const InlineTextBox* CachedLogicallyOrderedLeafBoxes::NextTextBox(
    const RootInlineBox* root,
    const InlineTextBox* box) {
  if (!root)
    return 0;

  CollectBoxes(root);

  // If box is null, root is box's next RootInlineBox, and nextBox is the first
  // logical box in root. Otherwise, root is box's RootInlineBox, and nextBox is
  // the next logical box in the same line.
  size_t next_box_index = 0;
  if (box)
    next_box_index = BoxIndexInLeaves(box) + 1;

  for (size_t i = next_box_index; i < leaf_boxes_.size(); ++i) {
    if (leaf_boxes_[i]->IsInlineTextBox())
      return ToInlineTextBox(leaf_boxes_[i]);
  }

  return 0;
}

const Vector<InlineBox*>& CachedLogicallyOrderedLeafBoxes::CollectBoxes(
    const RootInlineBox* root) {
  if (root_inline_box_ != root) {
    root_inline_box_ = root;
    leaf_boxes_.clear();
    root->CollectLeafBoxesInLogicalOrder(leaf_boxes_);
  }
  return leaf_boxes_;
}

int CachedLogicallyOrderedLeafBoxes::BoxIndexInLeaves(
    const InlineTextBox* box) const {
  for (size_t i = 0; i < leaf_boxes_.size(); ++i) {
    if (box == leaf_boxes_[i])
      return i;
  }
  return 0;
}

static const InlineTextBox* LogicallyPreviousBox(
    const VisiblePosition& visible_position,
    const InlineTextBox* text_box,
    bool& previous_box_in_different_block,
    CachedLogicallyOrderedLeafBoxes& leaf_boxes) {
  DCHECK(visible_position.IsValid()) << visible_position;
  const InlineBox* start_box = text_box;

  const InlineTextBox* previous_box =
      leaf_boxes.PreviousTextBox(&start_box->Root(), text_box);
  if (previous_box)
    return previous_box;

  previous_box = leaf_boxes.PreviousTextBox(start_box->Root().PrevRootBox(), 0);
  if (previous_box)
    return previous_box;

  while (1) {
    Node* start_node = start_box->GetLineLayoutItem().NonPseudoNode();
    if (!start_node)
      break;

    Position position = PreviousRootInlineBoxCandidatePosition(
        start_node, visible_position, kContentIsEditable);
    if (position.IsNull())
      break;

    RenderedPosition rendered_position(position, TextAffinity::kDownstream);
    RootInlineBox* previous_root = rendered_position.RootBox();
    if (!previous_root)
      break;

    previous_box = leaf_boxes.PreviousTextBox(previous_root, 0);
    if (previous_box) {
      previous_box_in_different_block = true;
      return previous_box;
    }

    if (!leaf_boxes.size())
      break;
    start_box = leaf_boxes.FirstBox();
  }
  return 0;
}

static const InlineTextBox* LogicallyNextBox(
    const VisiblePosition& visible_position,
    const InlineTextBox* text_box,
    bool& next_box_in_different_block,
    CachedLogicallyOrderedLeafBoxes& leaf_boxes) {
  DCHECK(visible_position.IsValid()) << visible_position;
  const InlineBox* start_box = text_box;

  const InlineTextBox* next_box =
      leaf_boxes.NextTextBox(&start_box->Root(), text_box);
  if (next_box)
    return next_box;

  next_box = leaf_boxes.NextTextBox(start_box->Root().NextRootBox(), 0);
  if (next_box)
    return next_box;

  while (1) {
    Node* start_node = start_box->GetLineLayoutItem().NonPseudoNode();
    if (!start_node)
      break;

    Position position = NextRootInlineBoxCandidatePosition(
        start_node, visible_position, kContentIsEditable);
    if (position.IsNull())
      break;

    RenderedPosition rendered_position(position, TextAffinity::kDownstream);
    RootInlineBox* next_root = rendered_position.RootBox();
    if (!next_root)
      break;

    next_box = leaf_boxes.NextTextBox(next_root, 0);
    if (next_box) {
      next_box_in_different_block = true;
      return next_box;
    }

    if (!leaf_boxes.size())
      break;
    start_box = leaf_boxes.FirstBox();
  }
  return 0;
}

static TextBreakIterator* WordBreakIteratorForMinOffsetBoundary(
    const VisiblePosition& visible_position,
    const InlineTextBox* text_box,
    int& previous_box_length,
    bool& previous_box_in_different_block,
    Vector<UChar, 1024>& string,
    CachedLogicallyOrderedLeafBoxes& leaf_boxes) {
  DCHECK(visible_position.IsValid()) << visible_position;
  previous_box_in_different_block = false;

  // FIXME: Handle the case when we don't have an inline text box.
  const InlineTextBox* previous_box = LogicallyPreviousBox(
      visible_position, text_box, previous_box_in_different_block, leaf_boxes);

  int len = 0;
  string.clear();
  if (previous_box) {
    previous_box_length = previous_box->Len();
    previous_box->GetLineLayoutItem().GetText().AppendTo(
        string, previous_box->Start(), previous_box_length);
    len += previous_box_length;
  }
  text_box->GetLineLayoutItem().GetText().AppendTo(string, text_box->Start(),
                                                   text_box->Len());
  len += text_box->Len();

  return WordBreakIterator(string.data(), len);
}

static TextBreakIterator* WordBreakIteratorForMaxOffsetBoundary(
    const VisiblePosition& visible_position,
    const InlineTextBox* text_box,
    bool& next_box_in_different_block,
    Vector<UChar, 1024>& string,
    CachedLogicallyOrderedLeafBoxes& leaf_boxes) {
  DCHECK(visible_position.IsValid()) << visible_position;
  next_box_in_different_block = false;

  // FIXME: Handle the case when we don't have an inline text box.
  const InlineTextBox* next_box = LogicallyNextBox(
      visible_position, text_box, next_box_in_different_block, leaf_boxes);

  int len = 0;
  string.clear();
  text_box->GetLineLayoutItem().GetText().AppendTo(string, text_box->Start(),
                                                   text_box->Len());
  len += text_box->Len();
  if (next_box) {
    next_box->GetLineLayoutItem().GetText().AppendTo(string, next_box->Start(),
                                                     next_box->Len());
    len += next_box->Len();
  }

  return WordBreakIterator(string.data(), len);
}

static bool IsLogicalStartOfWord(TextBreakIterator* iter,
                                 int position,
                                 bool hard_line_break) {
  bool boundary = hard_line_break ? true : iter->isBoundary(position);
  if (!boundary)
    return false;

  iter->following(position);
  // isWordTextBreak returns true after moving across a word and false after
  // moving across a punctuation/space.
  return IsWordTextBreak(iter);
}

static bool IslogicalEndOfWord(TextBreakIterator* iter,
                               int position,
                               bool hard_line_break) {
  bool boundary = iter->isBoundary(position);
  return (hard_line_break || boundary) && IsWordTextBreak(iter);
}

enum CursorMovementDirection { kMoveLeft, kMoveRight };

static VisiblePosition VisualWordPosition(
    const VisiblePosition& visible_position,
    CursorMovementDirection direction,
    bool skips_space_when_moving_right) {
  DCHECK(visible_position.IsValid()) << visible_position;
  if (visible_position.IsNull())
    return VisiblePosition();

  TextDirection block_direction =
      DirectionOfEnclosingBlock(visible_position.DeepEquivalent());
  InlineBox* previously_visited_box = 0;
  VisiblePosition current = visible_position;
  TextBreakIterator* iter = 0;

  CachedLogicallyOrderedLeafBoxes leaf_boxes;
  Vector<UChar, 1024> string;

  while (1) {
    VisiblePosition adjacent_character_position = direction == kMoveRight
                                                      ? RightPositionOf(current)
                                                      : LeftPositionOf(current);
    if (adjacent_character_position.DeepEquivalent() ==
            current.DeepEquivalent() ||
        adjacent_character_position.IsNull())
      return VisiblePosition();

    InlineBoxPosition box_position = ComputeInlineBoxPosition(
        adjacent_character_position.DeepEquivalent(), TextAffinity::kUpstream);
    InlineBox* box = box_position.inline_box;
    int offset_in_box = box_position.offset_in_box;

    if (!box)
      break;
    if (!box->IsInlineTextBox()) {
      current = adjacent_character_position;
      continue;
    }

    InlineTextBox* text_box = ToInlineTextBox(box);
    int previous_box_length = 0;
    bool previous_box_in_different_block = false;
    bool next_box_in_different_block = false;
    bool moving_into_new_box = previously_visited_box != box;

    if (offset_in_box == box->CaretMinOffset()) {
      iter = WordBreakIteratorForMinOffsetBoundary(
          visible_position, text_box, previous_box_length,
          previous_box_in_different_block, string, leaf_boxes);
    } else if (offset_in_box == box->CaretMaxOffset()) {
      iter = WordBreakIteratorForMaxOffsetBoundary(visible_position, text_box,
                                                   next_box_in_different_block,
                                                   string, leaf_boxes);
    } else if (moving_into_new_box) {
      iter = WordBreakIterator(text_box->GetLineLayoutItem().GetText(),
                               text_box->Start(), text_box->Len());
      previously_visited_box = box;
    }

    if (!iter)
      break;

    iter->first();
    int offset_in_iterator =
        offset_in_box - text_box->Start() + previous_box_length;

    bool is_word_break;
    bool box_has_same_directionality_as_block =
        box->Direction() == block_direction;
    bool moving_backward =
        (direction == kMoveLeft && box->Direction() == TextDirection::kLtr) ||
        (direction == kMoveRight && box->Direction() == TextDirection::kRtl);
    if ((skips_space_when_moving_right &&
         box_has_same_directionality_as_block) ||
        (!skips_space_when_moving_right && moving_backward)) {
      bool logical_start_in_layout_object =
          offset_in_box == static_cast<int>(text_box->Start()) &&
          previous_box_in_different_block;
      is_word_break = IsLogicalStartOfWord(iter, offset_in_iterator,
                                           logical_start_in_layout_object);
    } else {
      bool logical_end_in_layout_object =
          offset_in_box ==
              static_cast<int>(text_box->Start() + text_box->Len()) &&
          next_box_in_different_block;
      is_word_break = IslogicalEndOfWord(iter, offset_in_iterator,
                                         logical_end_in_layout_object);
    }

    if (is_word_break)
      return adjacent_character_position;

    current = adjacent_character_position;
  }
  return VisiblePosition();
}

VisiblePosition LeftWordPosition(const VisiblePosition& visible_position,
                                 bool skips_space_when_moving_right) {
  DCHECK(visible_position.IsValid()) << visible_position;
  VisiblePosition left_word_break = VisualWordPosition(
      visible_position, kMoveLeft, skips_space_when_moving_right);
  left_word_break = HonorEditingBoundaryAtOrBefore(
      left_word_break, visible_position.DeepEquivalent());

  // FIXME: How should we handle a non-editable position?
  if (left_word_break.IsNull() &&
      IsEditablePosition(visible_position.DeepEquivalent())) {
    TextDirection block_direction =
        DirectionOfEnclosingBlock(visible_position.DeepEquivalent());
    left_word_break = block_direction == TextDirection::kLtr
                          ? StartOfEditableContent(visible_position)
                          : EndOfEditableContent(visible_position);
  }
  return left_word_break;
}

VisiblePosition RightWordPosition(const VisiblePosition& visible_position,
                                  bool skips_space_when_moving_right) {
  DCHECK(visible_position.IsValid()) << visible_position;
  VisiblePosition right_word_break = VisualWordPosition(
      visible_position, kMoveRight, skips_space_when_moving_right);
  right_word_break = HonorEditingBoundaryAtOrBefore(
      right_word_break, visible_position.DeepEquivalent());

  // FIXME: How should we handle a non-editable position?
  if (right_word_break.IsNull() &&
      IsEditablePosition(visible_position.DeepEquivalent())) {
    TextDirection block_direction =
        DirectionOfEnclosingBlock(visible_position.DeepEquivalent());
    right_word_break = block_direction == TextDirection::kLtr
                           ? EndOfEditableContent(visible_position)
                           : StartOfEditableContent(visible_position);
  }
  return right_word_break;
}

template <typename Strategy>
static ContainerNode* NonShadowBoundaryParentNode(Node* node) {
  ContainerNode* parent = Strategy::Parent(*node);
  return parent && !parent->IsShadowRoot() ? parent : nullptr;
}

template <typename Strategy>
static Node* ParentEditingBoundary(const PositionTemplate<Strategy>& position) {
  Node* const anchor_node = position.AnchorNode();
  if (!anchor_node)
    return nullptr;

  Node* document_element = anchor_node->GetDocument().documentElement();
  if (!document_element)
    return nullptr;

  Node* boundary = position.ComputeContainerNode();
  while (boundary != document_element &&
         NonShadowBoundaryParentNode<Strategy>(boundary) &&
         HasEditableStyle(*anchor_node) ==
             HasEditableStyle(*Strategy::Parent(*boundary)))
    boundary = NonShadowBoundaryParentNode<Strategy>(boundary);

  return boundary;
}

enum BoundarySearchContextAvailability {
  kDontHaveMoreContext,
  kMayHaveMoreContext
};

typedef unsigned (*BoundarySearchFunction)(const UChar*,
                                           unsigned length,
                                           unsigned offset,
                                           BoundarySearchContextAvailability,
                                           bool& need_more_context);

template <typename Strategy>
static PositionTemplate<Strategy> PreviousBoundary(
    const VisiblePositionTemplate<Strategy>& c,
    BoundarySearchFunction search_function) {
  DCHECK(c.IsValid()) << c;
  const PositionTemplate<Strategy> pos = c.DeepEquivalent();
  Node* boundary = ParentEditingBoundary(pos);
  if (!boundary)
    return PositionTemplate<Strategy>();

  const PositionTemplate<Strategy> start =
      PositionTemplate<Strategy>::EditingPositionOf(boundary, 0)
          .ParentAnchoredEquivalent();
  const PositionTemplate<Strategy> end = pos.ParentAnchoredEquivalent();

  ForwardsTextBuffer suffix_string;
  if (RequiresContextForWordBoundary(CharacterBefore(c))) {
    TextIteratorAlgorithm<Strategy> forwards_iterator(
        end, PositionTemplate<Strategy>::AfterNode(boundary));
    while (!forwards_iterator.AtEnd()) {
      forwards_iterator.CopyTextTo(&suffix_string);
      int context_end_index = EndOfFirstWordBoundaryContext(
          suffix_string.Data() + suffix_string.Size() -
              forwards_iterator.length(),
          forwards_iterator.length());
      if (context_end_index < forwards_iterator.length()) {
        suffix_string.Shrink(forwards_iterator.length() - context_end_index);
        break;
      }
      forwards_iterator.Advance();
    }
  }

  unsigned suffix_length = suffix_string.Size();
  BackwardsTextBuffer string;
  string.PushRange(suffix_string.Data(), suffix_string.Size());

  SimplifiedBackwardsTextIteratorAlgorithm<Strategy> it(start, end);
  int remaining_length = 0;
  unsigned next = 0;
  bool need_more_context = false;
  while (!it.AtEnd()) {
    bool in_text_security_mode = it.IsInTextSecurityMode();
    // iterate to get chunks until the searchFunction returns a non-zero
    // value.
    if (!in_text_security_mode) {
      int run_offset = 0;
      do {
        run_offset += it.CopyTextTo(&string, run_offset, string.Capacity());
        // TODO(xiaochengh): The following line takes O(string.size()) time,
        // which makes quadratic overall running time in the worst case.
        // Should improve it in some way.
        next = search_function(string.Data(), string.Size(),
                               string.Size() - suffix_length,
                               kMayHaveMoreContext, need_more_context);
      } while (!next && run_offset < it.length());
      if (next) {
        remaining_length = it.length() - run_offset;
        break;
      }
    } else {
      // Treat bullets used in the text security mode as regular
      // characters when looking for boundaries
      string.PushCharacters('x', it.length());
      next = 0;
    }
    it.Advance();
  }
  if (need_more_context) {
    // The last search returned the beginning of the buffer and asked for
    // more context, but there is no earlier text. Force a search with
    // what's available.
    // TODO(xiaochengh): Do we have to search the whole string?
    next = search_function(string.Data(), string.Size(),
                           string.Size() - suffix_length, kDontHaveMoreContext,
                           need_more_context);
    DCHECK(!need_more_context);
  }

  if (!next)
    return it.AtEnd() ? it.StartPosition() : pos;

  Node* node = it.StartContainer();
  int boundary_offset = remaining_length + next;
  if (node->IsTextNode() && boundary_offset <= node->MaxCharacterOffset()) {
    // The next variable contains a usable index into a text node
    return PositionTemplate<Strategy>(node, boundary_offset);
  }

  // Use the character iterator to translate the next value into a DOM
  // position.
  BackwardsCharacterIteratorAlgorithm<Strategy> char_it(start, end);
  char_it.Advance(string.Size() - suffix_length - next);
  // TODO(yosin) charIt can get out of shadow host.
  return char_it.EndPosition();
}

template <typename Strategy>
static PositionTemplate<Strategy> NextBoundary(
    const VisiblePositionTemplate<Strategy>& c,
    BoundarySearchFunction search_function) {
  DCHECK(c.IsValid()) << c;
  PositionTemplate<Strategy> pos = c.DeepEquivalent();
  Node* boundary = ParentEditingBoundary(pos);
  if (!boundary)
    return PositionTemplate<Strategy>();

  Document& d = boundary->GetDocument();
  const PositionTemplate<Strategy> start(pos.ParentAnchoredEquivalent());

  BackwardsTextBuffer prefix_string;
  if (RequiresContextForWordBoundary(CharacterAfter(c))) {
    SimplifiedBackwardsTextIteratorAlgorithm<Strategy> backwards_iterator(
        PositionTemplate<Strategy>::FirstPositionInNode(&d), start);
    while (!backwards_iterator.AtEnd()) {
      backwards_iterator.CopyTextTo(&prefix_string);
      int context_start_index = StartOfLastWordBoundaryContext(
          prefix_string.Data(), backwards_iterator.length());
      if (context_start_index > 0) {
        prefix_string.Shrink(context_start_index);
        break;
      }
      backwards_iterator.Advance();
    }
  }

  unsigned prefix_length = prefix_string.Size();
  ForwardsTextBuffer string;
  string.PushRange(prefix_string.Data(), prefix_string.Size());

  const PositionTemplate<Strategy> search_start =
      PositionTemplate<Strategy>::EditingPositionOf(
          start.AnchorNode(), start.OffsetInContainerNode());
  const PositionTemplate<Strategy> search_end =
      PositionTemplate<Strategy>::LastPositionInNode(boundary);
  TextIteratorAlgorithm<Strategy> it(
      search_start, search_end,
      TextIteratorBehavior::Builder()
          .SetEmitsCharactersBetweenAllVisiblePositions(true)
          .Build());
  const unsigned kInvalidOffset = static_cast<unsigned>(-1);
  unsigned next = kInvalidOffset;
  unsigned offset = prefix_length;
  bool need_more_context = false;
  while (!it.AtEnd()) {
    // Keep asking the iterator for chunks until the search function
    // returns an end value not equal to the length of the string passed to
    // it.
    bool in_text_security_mode = it.IsInTextSecurityMode();
    if (!in_text_security_mode) {
      int run_offset = 0;
      do {
        run_offset += it.CopyTextTo(&string, run_offset, string.Capacity());
        next = search_function(string.Data(), string.Size(), offset,
                               kMayHaveMoreContext, need_more_context);
        if (!need_more_context) {
          // When the search does not need more context, skip all examined
          // characters except the last one, in case it is a boundary.
          offset = string.Size();
          U16_BACK_1(string.Data(), 0, offset);
        }
      } while (next == string.Size() && run_offset < it.length());
      if (next != string.Size())
        break;
    } else {
      // Treat bullets used in the text security mode as regular
      // characters when looking for boundaries
      string.PushCharacters('x', it.length());
      next = string.Size();
    }
    it.Advance();
  }
  if (need_more_context) {
    // The last search returned the end of the buffer and asked for more
    // context, but there is no further text. Force a search with what's
    // available.
    // TODO(xiaochengh): Do we still have to search the whole string?
    next = search_function(string.Data(), string.Size(), prefix_length,
                           kDontHaveMoreContext, need_more_context);
    DCHECK(!need_more_context);
  }

  if (it.AtEnd() && next == string.Size()) {
    pos = it.StartPositionInCurrentContainer();
  } else if (next != kInvalidOffset && next != prefix_length) {
    // Use the character iterator to translate the next value into a DOM
    // position.
    CharacterIteratorAlgorithm<Strategy> char_it(
        search_start, search_end,
        TextIteratorBehavior::Builder()
            .SetEmitsCharactersBetweenAllVisiblePositions(true)
            .Build());
    char_it.Advance(next - prefix_length - 1);
    pos = char_it.EndPosition();

    if (char_it.CharacterAt(0) == '\n') {
      // TODO(yosin) workaround for collapsed range (where only start
      // position is correct) emitted for some emitted newlines
      // (see rdar://5192593)
      const VisiblePositionTemplate<Strategy> vis_pos =
          CreateVisiblePosition(pos);
      if (vis_pos.DeepEquivalent() ==
          CreateVisiblePosition(char_it.StartPosition()).DeepEquivalent()) {
        char_it.Advance(1);
        pos = char_it.StartPosition();
      }
    }
  }

  return pos;
}

// ---------

static unsigned StartWordBoundary(
    const UChar* characters,
    unsigned length,
    unsigned offset,
    BoundarySearchContextAvailability may_have_more_context,
    bool& need_more_context) {
  TRACE_EVENT0("blink", "startWordBoundary");
  DCHECK(offset);
  if (may_have_more_context &&
      !StartOfLastWordBoundaryContext(characters, offset)) {
    need_more_context = true;
    return 0;
  }
  need_more_context = false;
  int start, end;
  U16_BACK_1(characters, 0, offset);
  FindWordBoundary(characters, length, offset, &start, &end);
  return start;
}

template <typename Strategy>
static PositionTemplate<Strategy> StartOfWordAlgorithm(
    const VisiblePositionTemplate<Strategy>& c,
    EWordSide side) {
  DCHECK(c.IsValid()) << c;
  // TODO(yosin) This returns a null VP for c at the start of the document
  // and |side| == |LeftWordIfOnBoundary|
  VisiblePositionTemplate<Strategy> p = c;
  if (side == kRightWordIfOnBoundary) {
    // at paragraph end, the startofWord is the current position
    if (IsEndOfParagraph(c))
      return c.DeepEquivalent();

    p = NextPositionOf(c);
    if (p.IsNull())
      return c.DeepEquivalent();
  }
  return PreviousBoundary(p, StartWordBoundary);
}

Position StartOfWordPosition(const VisiblePosition& position, EWordSide side) {
  return StartOfWordAlgorithm<EditingStrategy>(position, side);
}

VisiblePosition StartOfWord(const VisiblePosition& position, EWordSide side) {
  return CreateVisiblePosition(StartOfWordPosition(position, side));
}

PositionInFlatTree StartOfWordPosition(
    const VisiblePositionInFlatTree& position,
    EWordSide side) {
  return StartOfWordAlgorithm<EditingInFlatTreeStrategy>(position, side);
}

VisiblePositionInFlatTree StartOfWord(const VisiblePositionInFlatTree& position,
                                      EWordSide side) {
  return CreateVisiblePosition(StartOfWordPosition(position, side));
}

static unsigned EndWordBoundary(
    const UChar* characters,
    unsigned length,
    unsigned offset,
    BoundarySearchContextAvailability may_have_more_context,
    bool& need_more_context) {
  DCHECK_LE(offset, length);
  if (may_have_more_context &&
      EndOfFirstWordBoundaryContext(characters + offset, length - offset) ==
          static_cast<int>(length - offset)) {
    need_more_context = true;
    return length;
  }
  need_more_context = false;
  return FindWordEndBoundary(characters, length, offset);
}

template <typename Strategy>
static PositionTemplate<Strategy> EndOfWordAlgorithm(
    const VisiblePositionTemplate<Strategy>& c,
    EWordSide side) {
  DCHECK(c.IsValid()) << c;
  VisiblePositionTemplate<Strategy> p = c;
  if (side == kLeftWordIfOnBoundary) {
    if (IsStartOfParagraph(c))
      return c.DeepEquivalent();

    p = PreviousPositionOf(c);
    if (p.IsNull())
      return c.DeepEquivalent();
  } else if (IsEndOfParagraph(c)) {
    return c.DeepEquivalent();
  }

  return NextBoundary(p, EndWordBoundary);
}

Position EndOfWordPosition(const VisiblePosition& position, EWordSide side) {
  return EndOfWordAlgorithm<EditingStrategy>(position, side);
}

VisiblePosition EndOfWord(const VisiblePosition& position, EWordSide side) {
  return CreateVisiblePosition(EndOfWordPosition(position, side),
                               VP_UPSTREAM_IF_POSSIBLE);
}

PositionInFlatTree EndOfWordPosition(const VisiblePositionInFlatTree& position,
                                     EWordSide side) {
  return EndOfWordAlgorithm<EditingInFlatTreeStrategy>(position, side);
}

VisiblePositionInFlatTree EndOfWord(const VisiblePositionInFlatTree& position,
                                    EWordSide side) {
  return CreateVisiblePosition(EndOfWordPosition(position, side),
                               VP_UPSTREAM_IF_POSSIBLE);
}

static unsigned PreviousWordPositionBoundary(
    const UChar* characters,
    unsigned length,
    unsigned offset,
    BoundarySearchContextAvailability may_have_more_context,
    bool& need_more_context) {
  if (may_have_more_context &&
      !StartOfLastWordBoundaryContext(characters, offset)) {
    need_more_context = true;
    return 0;
  }
  need_more_context = false;
  return FindNextWordFromIndex(characters, length, offset, false);
}

VisiblePosition PreviousWordPosition(const VisiblePosition& c) {
  DCHECK(c.IsValid()) << c;
  VisiblePosition prev =
      CreateVisiblePosition(PreviousBoundary(c, PreviousWordPositionBoundary));
  return HonorEditingBoundaryAtOrBefore(prev, c.DeepEquivalent());
}

static unsigned NextWordPositionBoundary(
    const UChar* characters,
    unsigned length,
    unsigned offset,
    BoundarySearchContextAvailability may_have_more_context,
    bool& need_more_context) {
  if (may_have_more_context &&
      EndOfFirstWordBoundaryContext(characters + offset, length - offset) ==
          static_cast<int>(length - offset)) {
    need_more_context = true;
    return length;
  }
  need_more_context = false;
  return FindNextWordFromIndex(characters, length, offset, true);
}

VisiblePosition NextWordPosition(const VisiblePosition& c) {
  DCHECK(c.IsValid()) << c;
  VisiblePosition next = CreateVisiblePosition(
      NextBoundary(c, NextWordPositionBoundary), VP_UPSTREAM_IF_POSSIBLE);
  return HonorEditingBoundaryAtOrAfter(next, c.DeepEquivalent());
}

// ---------

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,
                                      BoundarySearchContextAvailability,
                                      bool&) {
  TextBreakIterator* iterator = SentenceBreakIterator(characters, length);
  // FIXME: The following function can return -1; we don't handle that.
  return iterator->preceding(length);
}

template <typename Strategy>
static VisiblePositionTemplate<Strategy> StartOfSentenceAlgorithm(
    const VisiblePositionTemplate<Strategy>& c) {
  DCHECK(c.IsValid()) << c;
  return CreateVisiblePosition(PreviousBoundary(c, StartSentenceBoundary));
}

VisiblePosition StartOfSentence(const VisiblePosition& c) {
  return StartOfSentenceAlgorithm<EditingStrategy>(c);
}

VisiblePositionInFlatTree StartOfSentence(const VisiblePositionInFlatTree& c) {
  return StartOfSentenceAlgorithm<EditingInFlatTreeStrategy>(c);
}

static unsigned EndSentenceBoundary(const UChar* characters,
                                    unsigned length,
                                    unsigned,
                                    BoundarySearchContextAvailability,
                                    bool&) {
  TextBreakIterator* iterator = SentenceBreakIterator(characters, length);
  return iterator->next();
}

// TODO(yosin) This includes the space after the punctuation that marks the end
// of the sentence.
template <typename Strategy>
static VisiblePositionTemplate<Strategy> EndOfSentenceAlgorithm(
    const VisiblePositionTemplate<Strategy>& c) {
  DCHECK(c.IsValid()) << c;
  return CreateVisiblePosition(NextBoundary(c, EndSentenceBoundary),
                               VP_UPSTREAM_IF_POSSIBLE);
}

VisiblePosition EndOfSentence(const VisiblePosition& c) {
  return EndOfSentenceAlgorithm<EditingStrategy>(c);
}

VisiblePositionInFlatTree EndOfSentence(const VisiblePositionInFlatTree& c) {
  return EndOfSentenceAlgorithm<EditingInFlatTreeStrategy>(c);
}

static unsigned PreviousSentencePositionBoundary(
    const UChar* characters,
    unsigned length,
    unsigned,
    BoundarySearchContextAvailability,
    bool&) {
  // FIXME: This is identical to startSentenceBoundary. I'm pretty sure that's
  // not right.
  TextBreakIterator* iterator = SentenceBreakIterator(characters, length);
  // FIXME: The following function can return -1; we don't handle that.
  return iterator->preceding(length);
}

VisiblePosition PreviousSentencePosition(const VisiblePosition& c) {
  DCHECK(c.IsValid()) << c;
  VisiblePosition prev = CreateVisiblePosition(
      PreviousBoundary(c, PreviousSentencePositionBoundary));
  return HonorEditingBoundaryAtOrBefore(prev, c.DeepEquivalent());
}

static unsigned NextSentencePositionBoundary(const UChar* characters,
                                             unsigned length,
                                             unsigned,
                                             BoundarySearchContextAvailability,
                                             bool&) {
  // FIXME: This is identical to endSentenceBoundary. This isn't right, it needs
  // to move to the equivlant position in the following sentence.
  TextBreakIterator* iterator = SentenceBreakIterator(characters, length);
  return iterator->following(0);
}

VisiblePosition NextSentencePosition(const VisiblePosition& c) {
  DCHECK(c.IsValid()) << c;
  VisiblePosition next = CreateVisiblePosition(
      NextBoundary(c, NextSentencePositionBoundary), VP_UPSTREAM_IF_POSSIBLE);
  return HonorEditingBoundaryAtOrAfter(next, c.DeepEquivalent());
}

EphemeralRange ExpandEndToSentenceBoundary(const EphemeralRange& range) {
  DCHECK(range.IsNotNull());
  const VisiblePosition& visible_end =
      CreateVisiblePosition(range.EndPosition());
  DCHECK(visible_end.IsNotNull());
  const Position& sentence_end = EndOfSentence(visible_end).DeepEquivalent();
  // TODO(xiaochengh): |sentenceEnd < range.endPosition()| is possible,
  // which would trigger a DCHECK in EphemeralRange's constructor if we return
  // it directly. However, this shouldn't happen and needs to be fixed.
  return EphemeralRange(
      range.StartPosition(),
      sentence_end.IsNotNull() && sentence_end > range.EndPosition()
          ? sentence_end
          : range.EndPosition());
}

EphemeralRange ExpandRangeToSentenceBoundary(const EphemeralRange& range) {
  DCHECK(range.IsNotNull());
  const VisiblePosition& visible_start =
      CreateVisiblePosition(range.StartPosition());
  DCHECK(visible_start.IsNotNull());
  const Position& sentence_start =
      StartOfSentence(visible_start).DeepEquivalent();
  // TODO(xiaochengh): |sentenceStart > range.startPosition()| is possible,
  // which would trigger a DCHECK in EphemeralRange's constructor if we return
  // it directly. However, this shouldn't happen and needs to be fixed.
  return ExpandEndToSentenceBoundary(EphemeralRange(
      sentence_start.IsNotNull() && sentence_start < range.StartPosition()
          ? sentence_start
          : range.StartPosition(),
      range.EndPosition()));
}

static bool NodeIsUserSelectAll(const Node* node) {
  return node && node->GetLayoutObject() &&
         node->GetLayoutObject()->Style()->UserSelect() == EUserSelect::kAll;
}

template <typename Strategy>
PositionTemplate<Strategy> StartOfParagraphAlgorithm(
    const PositionTemplate<Strategy>& position,
    EditingBoundaryCrossingRule boundary_crossing_rule) {
  Node* const start_node = position.AnchorNode();

  if (!start_node)
    return PositionTemplate<Strategy>();

  if (IsRenderedAsNonInlineTableImageOrHR(start_node))
    return PositionTemplate<Strategy>::BeforeNode(start_node);

  Element* const start_block = EnclosingBlock(
      PositionTemplate<Strategy>::FirstPositionInOrBeforeNode(start_node),
      kCannotCrossEditingBoundary);
  ContainerNode* const highest_root = HighestEditableRoot(position);
  const bool start_node_is_editable = HasEditableStyle(*start_node);

  Node* candidate_node = start_node;
  PositionAnchorType candidate_type = position.AnchorType();
  int candidate_offset = position.ComputeEditingOffset();

  Node* previous_node_iterator = start_node;
  while (previous_node_iterator) {
    if (boundary_crossing_rule == kCannotCrossEditingBoundary &&
        !NodeIsUserSelectAll(previous_node_iterator) &&
        HasEditableStyle(*previous_node_iterator) != start_node_is_editable)
      break;
    if (boundary_crossing_rule == kCanSkipOverEditingBoundary) {
      while (previous_node_iterator &&
             HasEditableStyle(*previous_node_iterator) !=
                 start_node_is_editable) {
        previous_node_iterator =
            Strategy::PreviousPostOrder(*previous_node_iterator, start_block);
      }
      if (!previous_node_iterator ||
          !previous_node_iterator->IsDescendantOf(highest_root))
        break;
    }

    const LayoutItem layout_item =
        LayoutItem(previous_node_iterator->GetLayoutObject());
    if (layout_item.IsNull()) {
      previous_node_iterator =
          Strategy::PreviousPostOrder(*previous_node_iterator, start_block);
      continue;
    }
    const ComputedStyle& style = layout_item.StyleRef();
    if (style.Visibility() != EVisibility::kVisible) {
      previous_node_iterator =
          Strategy::PreviousPostOrder(*previous_node_iterator, start_block);
      continue;
    }

    if (layout_item.IsBR() || IsEnclosingBlock(previous_node_iterator))
      break;

    if (layout_item.IsText() &&
        ToLayoutText(previous_node_iterator->GetLayoutObject())
            ->ResolvedTextLength()) {
      SECURITY_DCHECK(previous_node_iterator->IsTextNode());
      if (style.PreserveNewline()) {
        LayoutText* text =
            ToLayoutText(previous_node_iterator->GetLayoutObject());
        int index = text->TextLength();
        if (previous_node_iterator == start_node && candidate_offset < index)
          index = max(0, candidate_offset);
        while (--index >= 0) {
          if ((*text)[index] == '\n')
            return PositionTemplate<Strategy>(ToText(previous_node_iterator),
                                              index + 1);
        }
      }
      candidate_node = previous_node_iterator;
      candidate_type = PositionAnchorType::kOffsetInAnchor;
      candidate_offset = 0;
      previous_node_iterator =
          Strategy::PreviousPostOrder(*previous_node_iterator, start_block);
    } else if (EditingIgnoresContent(*previous_node_iterator) ||
               IsDisplayInsideTable(previous_node_iterator)) {
      candidate_node = previous_node_iterator;
      candidate_type = PositionAnchorType::kBeforeAnchor;
      previous_node_iterator = previous_node_iterator->previousSibling()
                                   ? previous_node_iterator->previousSibling()
                                   : Strategy::PreviousPostOrder(
                                         *previous_node_iterator, start_block);
    } else {
      previous_node_iterator =
          Strategy::PreviousPostOrder(*previous_node_iterator, start_block);
    }
  }

  if (candidate_type == PositionAnchorType::kOffsetInAnchor)
    return PositionTemplate<Strategy>(candidate_node, candidate_offset);

  return PositionTemplate<Strategy>(candidate_node, candidate_type);
}

template <typename Strategy>
VisiblePositionTemplate<Strategy> StartOfParagraphAlgorithm(
    const VisiblePositionTemplate<Strategy>& visible_position,
    EditingBoundaryCrossingRule boundary_crossing_rule) {
  DCHECK(visible_position.IsValid()) << visible_position;
  return CreateVisiblePosition(StartOfParagraphAlgorithm(
      visible_position.DeepEquivalent(), boundary_crossing_rule));
}

VisiblePosition StartOfParagraph(
    const VisiblePosition& c,
    EditingBoundaryCrossingRule boundary_crossing_rule) {
  return StartOfParagraphAlgorithm<EditingStrategy>(c, boundary_crossing_rule);
}

VisiblePositionInFlatTree StartOfParagraph(
    const VisiblePositionInFlatTree& c,
    EditingBoundaryCrossingRule boundary_crossing_rule) {
  return StartOfParagraphAlgorithm<EditingInFlatTreeStrategy>(
      c, boundary_crossing_rule);
}

template <typename Strategy>
static PositionTemplate<Strategy> EndOfParagraphAlgorithm(
    const PositionTemplate<Strategy>& position,
    EditingBoundaryCrossingRule boundary_crossing_rule) {
  Node* const start_node = position.AnchorNode();

  if (!start_node)
    return PositionTemplate<Strategy>();

  if (IsRenderedAsNonInlineTableImageOrHR(start_node))
    return PositionTemplate<Strategy>::AfterNode(start_node);

  Element* const start_block = EnclosingBlock(
      PositionTemplate<Strategy>::FirstPositionInOrBeforeNode(start_node),
      kCannotCrossEditingBoundary);
  ContainerNode* const highest_root = HighestEditableRoot(position);
  const bool start_node_is_editable = HasEditableStyle(*start_node);

  Node* candidate_node = start_node;
  PositionAnchorType candidate_type = position.AnchorType();
  int candidate_offset = position.ComputeEditingOffset();

  Node* next_node_iterator = start_node;
  while (next_node_iterator) {
    if (boundary_crossing_rule == kCannotCrossEditingBoundary &&
        !NodeIsUserSelectAll(next_node_iterator) &&
        HasEditableStyle(*next_node_iterator) != start_node_is_editable)
      break;
    if (boundary_crossing_rule == kCanSkipOverEditingBoundary) {
      while (next_node_iterator &&
             HasEditableStyle(*next_node_iterator) != start_node_is_editable)
        next_node_iterator = Strategy::Next(*next_node_iterator, start_block);
      if (!next_node_iterator ||
          !next_node_iterator->IsDescendantOf(highest_root))
        break;
    }

    LayoutObject* const layout_object = next_node_iterator->GetLayoutObject();
    if (!layout_object) {
      next_node_iterator = Strategy::Next(*next_node_iterator, start_block);
      continue;
    }
    const ComputedStyle& style = layout_object->StyleRef();
    if (style.Visibility() != EVisibility::kVisible) {
      next_node_iterator = Strategy::Next(*next_node_iterator, start_block);
      continue;
    }

    if (layout_object->IsBR() || IsEnclosingBlock(next_node_iterator))
      break;

    // FIXME: We avoid returning a position where the layoutObject can't accept
    // the caret.
    if (layout_object->IsText() &&
        ToLayoutText(layout_object)->ResolvedTextLength()) {
      SECURITY_DCHECK(next_node_iterator->IsTextNode());
      LayoutText* const text = ToLayoutText(layout_object);
      if (style.PreserveNewline()) {
        const int length = ToLayoutText(layout_object)->TextLength();
        for (int i = (next_node_iterator == start_node ? candidate_offset : 0);
             i < length; ++i) {
          if ((*text)[i] == '\n')
            return PositionTemplate<Strategy>(ToText(next_node_iterator),
                                              i + text->TextStartOffset());
        }
      }

      candidate_node = next_node_iterator;
      candidate_type = PositionAnchorType::kOffsetInAnchor;
      candidate_offset =
          layout_object->CaretMaxOffset() + text->TextStartOffset();
      next_node_iterator = Strategy::Next(*next_node_iterator, start_block);
    } else if (EditingIgnoresContent(*next_node_iterator) ||
               IsDisplayInsideTable(next_node_iterator)) {
      candidate_node = next_node_iterator;
      candidate_type = PositionAnchorType::kAfterAnchor;
      next_node_iterator =
          Strategy::NextSkippingChildren(*next_node_iterator, start_block);
    } else {
      next_node_iterator = Strategy::Next(*next_node_iterator, start_block);
    }
  }

  if (candidate_type == PositionAnchorType::kOffsetInAnchor)
    return PositionTemplate<Strategy>(candidate_node, candidate_offset);

  return PositionTemplate<Strategy>(candidate_node, candidate_type);
}

template <typename Strategy>
static VisiblePositionTemplate<Strategy> EndOfParagraphAlgorithm(
    const VisiblePositionTemplate<Strategy>& visible_position,
    EditingBoundaryCrossingRule boundary_crossing_rule) {
  DCHECK(visible_position.IsValid()) << visible_position;
  return CreateVisiblePosition(EndOfParagraphAlgorithm(
      visible_position.DeepEquivalent(), boundary_crossing_rule));
}

VisiblePosition EndOfParagraph(
    const VisiblePosition& c,
    EditingBoundaryCrossingRule boundary_crossing_rule) {
  return EndOfParagraphAlgorithm<EditingStrategy>(c, boundary_crossing_rule);
}

VisiblePositionInFlatTree EndOfParagraph(
    const VisiblePositionInFlatTree& c,
    EditingBoundaryCrossingRule boundary_crossing_rule) {
  return EndOfParagraphAlgorithm<EditingInFlatTreeStrategy>(
      c, boundary_crossing_rule);
}

// FIXME: isStartOfParagraph(startOfNextParagraph(pos)) is not always true
VisiblePosition StartOfNextParagraph(const VisiblePosition& visible_position) {
  DCHECK(visible_position.IsValid()) << visible_position;
  VisiblePosition paragraph_end(
      EndOfParagraph(visible_position, kCanSkipOverEditingBoundary));
  VisiblePosition after_paragraph_end(
      NextPositionOf(paragraph_end, kCannotCrossEditingBoundary));
  // The position after the last position in the last cell of a table
  // is not the start of the next paragraph.
  if (TableElementJustBefore(after_paragraph_end))
    return NextPositionOf(after_paragraph_end, kCannotCrossEditingBoundary);
  return after_paragraph_end;
}

// FIXME: isStartOfParagraph(startOfNextParagraph(pos)) is not always true
bool InSameParagraph(const VisiblePosition& a,
                     const VisiblePosition& b,
                     EditingBoundaryCrossingRule boundary_crossing_rule) {
  DCHECK(a.IsValid()) << a;
  DCHECK(b.IsValid()) << b;
  return a.IsNotNull() &&
         StartOfParagraph(a, boundary_crossing_rule).DeepEquivalent() ==
             StartOfParagraph(b, boundary_crossing_rule).DeepEquivalent();
}

template <typename Strategy>
static bool IsStartOfParagraphAlgorithm(
    const VisiblePositionTemplate<Strategy>& pos,
    EditingBoundaryCrossingRule boundary_crossing_rule) {
  DCHECK(pos.IsValid()) << pos;
  return pos.IsNotNull() &&
         pos.DeepEquivalent() ==
             StartOfParagraph(pos, boundary_crossing_rule).DeepEquivalent();
}

bool IsStartOfParagraph(const VisiblePosition& pos,
                        EditingBoundaryCrossingRule boundary_crossing_rule) {
  return IsStartOfParagraphAlgorithm<EditingStrategy>(pos,
                                                      boundary_crossing_rule);
}

bool IsStartOfParagraph(const VisiblePositionInFlatTree& pos,
                        EditingBoundaryCrossingRule boundary_crossing_rule) {
  return IsStartOfParagraphAlgorithm<EditingInFlatTreeStrategy>(
      pos, boundary_crossing_rule);
}

template <typename Strategy>
static bool IsEndOfParagraphAlgorithm(
    const VisiblePositionTemplate<Strategy>& pos,
    EditingBoundaryCrossingRule boundary_crossing_rule) {
  DCHECK(pos.IsValid()) << pos;
  return pos.IsNotNull() &&
         pos.DeepEquivalent() ==
             EndOfParagraph(pos, boundary_crossing_rule).DeepEquivalent();
}

bool IsEndOfParagraph(const VisiblePosition& pos,
                      EditingBoundaryCrossingRule boundary_crossing_rule) {
  return IsEndOfParagraphAlgorithm<EditingStrategy>(pos,
                                                    boundary_crossing_rule);
}

bool IsEndOfParagraph(const VisiblePositionInFlatTree& pos,
                      EditingBoundaryCrossingRule boundary_crossing_rule) {
  return IsEndOfParagraphAlgorithm<EditingInFlatTreeStrategy>(
      pos, boundary_crossing_rule);
}

VisiblePosition PreviousParagraphPosition(const VisiblePosition& p,
                                          LayoutUnit x) {
  DCHECK(p.IsValid()) << p;
  VisiblePosition pos = p;
  do {
    VisiblePosition n = PreviousLinePosition(pos, x);
    if (n.IsNull() || n.DeepEquivalent() == pos.DeepEquivalent())
      break;
    pos = n;
  } while (InSameParagraph(p, pos));
  return pos;
}

VisiblePosition NextParagraphPosition(const VisiblePosition& p, LayoutUnit x) {
  DCHECK(p.IsValid()) << p;
  VisiblePosition pos = p;
  do {
    VisiblePosition n = NextLinePosition(pos, x);
    if (n.IsNull() || n.DeepEquivalent() == pos.DeepEquivalent())
      break;
    pos = n;
  } while (InSameParagraph(p, pos));
  return pos;
}

EphemeralRange ExpandToParagraphBoundary(const EphemeralRange& range) {
  const VisiblePosition& start = CreateVisiblePosition(range.StartPosition());
  DCHECK(start.IsNotNull()) << range.StartPosition();
  const Position& paragraph_start = StartOfParagraph(start).DeepEquivalent();
  DCHECK(paragraph_start.IsNotNull()) << range.StartPosition();

  const VisiblePosition& end = CreateVisiblePosition(range.EndPosition());
  DCHECK(end.IsNotNull()) << range.EndPosition();
  const Position& paragraph_end = EndOfParagraph(end).DeepEquivalent();
  DCHECK(paragraph_end.IsNotNull()) << range.EndPosition();

  // TODO(xiaochengh): There are some cases (crbug.com/640112) where we get
  // |paragraphStart > paragraphEnd|, which is the reason we cannot directly
  // return |EphemeralRange(paragraphStart, paragraphEnd)|. This is not
  // desired, though. We should do more investigation to ensure that why
  // |paragraphStart <= paragraphEnd| is violated.
  const Position& result_start =
      paragraph_start.IsNotNull() && paragraph_start <= range.StartPosition()
          ? paragraph_start
          : range.StartPosition();
  const Position& result_end =
      paragraph_end.IsNotNull() && paragraph_end >= range.EndPosition()
          ? paragraph_end
          : range.EndPosition();
  return EphemeralRange(result_start, result_end);
}

// ---------

VisiblePosition StartOfBlock(const VisiblePosition& visible_position,
                             EditingBoundaryCrossingRule rule) {
  DCHECK(visible_position.IsValid()) << visible_position;
  Position position = visible_position.DeepEquivalent();
  Element* start_block =
      position.ComputeContainerNode()
          ? EnclosingBlock(position.ComputeContainerNode(), rule)
          : 0;
  return start_block ? VisiblePosition::FirstPositionInNode(start_block)
                     : VisiblePosition();
}

VisiblePosition EndOfBlock(const VisiblePosition& visible_position,
                           EditingBoundaryCrossingRule rule) {
  DCHECK(visible_position.IsValid()) << visible_position;
  Position position = visible_position.DeepEquivalent();
  Element* end_block =
      position.ComputeContainerNode()
          ? EnclosingBlock(position.ComputeContainerNode(), rule)
          : 0;
  return end_block ? VisiblePosition::LastPositionInNode(end_block)
                   : VisiblePosition();
}

bool InSameBlock(const VisiblePosition& a, const VisiblePosition& b) {
  DCHECK(a.IsValid()) << a;
  DCHECK(b.IsValid()) << b;
  return !a.IsNull() &&
         EnclosingBlock(a.DeepEquivalent().ComputeContainerNode()) ==
             EnclosingBlock(b.DeepEquivalent().ComputeContainerNode());
}

bool IsStartOfBlock(const VisiblePosition& pos) {
  DCHECK(pos.IsValid()) << pos;
  return pos.IsNotNull() &&
         pos.DeepEquivalent() ==
             StartOfBlock(pos, kCanCrossEditingBoundary).DeepEquivalent();
}

bool IsEndOfBlock(const VisiblePosition& pos) {
  DCHECK(pos.IsValid()) << pos;
  return pos.IsNotNull() &&
         pos.DeepEquivalent() ==
             EndOfBlock(pos, kCanCrossEditingBoundary).DeepEquivalent();
}

// ---------

template <typename Strategy>
static VisiblePositionTemplate<Strategy> StartOfDocumentAlgorithm(
    const VisiblePositionTemplate<Strategy>& visible_position) {
  DCHECK(visible_position.IsValid()) << visible_position;
  Node* node = visible_position.DeepEquivalent().AnchorNode();
  if (!node || !node->GetDocument().documentElement())
    return VisiblePositionTemplate<Strategy>();

  return CreateVisiblePosition(PositionTemplate<Strategy>::FirstPositionInNode(
      node->GetDocument().documentElement()));
}

VisiblePosition StartOfDocument(const VisiblePosition& c) {
  return StartOfDocumentAlgorithm<EditingStrategy>(c);
}

VisiblePositionInFlatTree StartOfDocument(const VisiblePositionInFlatTree& c) {
  return StartOfDocumentAlgorithm<EditingInFlatTreeStrategy>(c);
}

template <typename Strategy>
static VisiblePositionTemplate<Strategy> EndOfDocumentAlgorithm(
    const VisiblePositionTemplate<Strategy>& visible_position) {
  DCHECK(visible_position.IsValid()) << visible_position;
  Node* node = visible_position.DeepEquivalent().AnchorNode();
  if (!node || !node->GetDocument().documentElement())
    return VisiblePositionTemplate<Strategy>();

  Element* doc = node->GetDocument().documentElement();
  return CreateVisiblePosition(
      PositionTemplate<Strategy>::LastPositionInNode(doc));
}

VisiblePosition EndOfDocument(const VisiblePosition& c) {
  return EndOfDocumentAlgorithm<EditingStrategy>(c);
}

VisiblePositionInFlatTree EndOfDocument(const VisiblePositionInFlatTree& c) {
  return EndOfDocumentAlgorithm<EditingInFlatTreeStrategy>(c);
}

bool IsStartOfDocument(const VisiblePosition& p) {
  DCHECK(p.IsValid()) << p;
  return p.IsNotNull() &&
         PreviousPositionOf(p, kCanCrossEditingBoundary).IsNull();
}

bool IsEndOfDocument(const VisiblePosition& p) {
  DCHECK(p.IsValid()) << p;
  return p.IsNotNull() && NextPositionOf(p, kCanCrossEditingBoundary).IsNull();
}

// ---------

VisiblePosition StartOfEditableContent(
    const VisiblePosition& visible_position) {
  DCHECK(visible_position.IsValid()) << visible_position;
  ContainerNode* highest_root =
      HighestEditableRoot(visible_position.DeepEquivalent());
  if (!highest_root)
    return VisiblePosition();

  return VisiblePosition::FirstPositionInNode(highest_root);
}

VisiblePosition EndOfEditableContent(const VisiblePosition& visible_position) {
  DCHECK(visible_position.IsValid()) << visible_position;
  ContainerNode* highest_root =
      HighestEditableRoot(visible_position.DeepEquivalent());
  if (!highest_root)
    return VisiblePosition();

  return VisiblePosition::LastPositionInNode(highest_root);
}

bool IsEndOfEditableOrNonEditableContent(const VisiblePosition& position) {
  DCHECK(position.IsValid()) << position;
  return position.IsNotNull() && NextPositionOf(position).IsNull();
}

// TODO(yosin) We should rename |isEndOfEditableOrNonEditableContent()| what
// this function does, e.g. |isLastVisiblePositionOrEndOfInnerEditor()|.
bool IsEndOfEditableOrNonEditableContent(
    const VisiblePositionInFlatTree& position) {
  DCHECK(position.IsValid()) << position;
  if (position.IsNull())
    return false;
  const VisiblePositionInFlatTree next_position = NextPositionOf(position);
  if (next_position.IsNull())
    return true;
  // In DOM version, following condition, the last position of inner editor
  // of INPUT/TEXTAREA element, by |nextPosition().isNull()|, because of
  // an inner editor is an only leaf node.
  if (!next_position.DeepEquivalent().IsAfterAnchor())
    return false;
  return IsTextControlElement(next_position.DeepEquivalent().AnchorNode());
}

VisiblePosition LeftBoundaryOfLine(const VisiblePosition& c,
                                   TextDirection direction) {
  DCHECK(c.IsValid()) << c;
  return direction == TextDirection::kLtr ? LogicalStartOfLine(c)
                                          : LogicalEndOfLine(c);
}

VisiblePosition RightBoundaryOfLine(const VisiblePosition& c,
                                    TextDirection direction) {
  DCHECK(c.IsValid()) << c;
  return direction == TextDirection::kLtr ? 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* layout_object) {
  LayoutBlock* container = layout_object->ContainingBlock();
  for (LayoutObject* next = layout_object->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 min_offset = INT_MAX;
      for (InlineTextBox* box = ToLayoutText(next)->FirstTextBox(); box;
           box = box->NextTextBox()) {
        int caret_min_offset = box->CaretMinOffset();
        if (caret_min_offset < min_offset) {
          match = box;
          min_offset = caret_min_offset;
        }
      }
      if (match)
        return match;
    }
  }
  return 0;
}

template <typename Strategy>
PositionTemplate<Strategy> DownstreamIgnoringEditingBoundaries(
    PositionTemplate<Strategy> position) {
  PositionTemplate<Strategy> last_position;
  while (!position.IsEquivalent(last_position)) {
    last_position = position;
    position = MostForwardCaretPosition(position, kCanCrossEditingBoundary);
  }
  return position;
}

template <typename Strategy>
PositionTemplate<Strategy> UpstreamIgnoringEditingBoundaries(
    PositionTemplate<Strategy> position) {
  PositionTemplate<Strategy> last_position;
  while (!position.IsEquivalent(last_position)) {
    last_position = position;
    position = MostBackwardCaretPosition(position, kCanCrossEditingBoundary);
  }
  return position;
}

// Returns true if |inlineBox| starts different direction of embedded text ru.
// See [1] for details.
// [1] UNICODE BIDIRECTIONAL ALGORITHM, http://unicode.org/reports/tr9/
static bool IsStartOfDifferentDirection(const InlineBox* inline_box) {
  InlineBox* prev_box = inline_box->PrevLeafChild();
  if (!prev_box)
    return true;
  if (prev_box->Direction() == inline_box->Direction())
    return true;
  DCHECK_NE(prev_box->BidiLevel(), inline_box->BidiLevel());
  return prev_box->BidiLevel() > inline_box->BidiLevel();
}

template <typename Strategy>
static InlineBoxPosition ComputeInlineBoxPositionTemplate(
    const PositionTemplate<Strategy>& position,
    TextAffinity affinity,
    TextDirection primary_direction) {
  InlineBox* inline_box = nullptr;
  int caret_offset = position.ComputeEditingOffset();
  Node* const anchor_node = position.AnchorNode();
  LayoutObject* layout_object =
      anchor_node->IsShadowRoot()
          ? ToShadowRoot(anchor_node)->host().GetLayoutObject()
          : anchor_node->GetLayoutObject();

  DCHECK(layout_object) << position;

  if (!layout_object->IsText()) {
    inline_box = 0;
    if (CanHaveChildrenForEditing(anchor_node) &&
        layout_object->IsLayoutBlockFlow() &&
        HasRenderedNonAnonymousDescendantsWithHeight(layout_object)) {
      // 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::createPositionWithAffinity()|.
      PositionTemplate<Strategy> equivalent =
          DownstreamIgnoringEditingBoundaries(position);
      if (equivalent == position) {
        equivalent = UpstreamIgnoringEditingBoundaries(position);
        if (equivalent == position ||
            DownstreamIgnoringEditingBoundaries(equivalent) == position)
          return InlineBoxPosition(inline_box, caret_offset);
      }

      return ComputeInlineBoxPosition(equivalent, TextAffinity::kUpstream,
                                      primary_direction);
    }
    if (layout_object->IsBox()) {
      inline_box = ToLayoutBox(layout_object)->InlineBoxWrapper();
      if (!inline_box || (caret_offset > inline_box->CaretMinOffset() &&
                          caret_offset < inline_box->CaretMaxOffset()))
        return InlineBoxPosition(inline_box, caret_offset);
    }
  } else {
    LayoutText* text_layout_object = ToLayoutText(layout_object);

    InlineTextBox* box;
    InlineTextBox* candidate = 0;

    for (box = text_layout_object->FirstTextBox(); box;
         box = box->NextTextBox()) {
      int caret_min_offset = box->CaretMinOffset();
      int caret_max_offset = box->CaretMaxOffset();

      if (caret_offset < caret_min_offset || caret_offset > caret_max_offset ||
          (caret_offset == caret_max_offset && box->IsLineBreak()))
        continue;

      if (caret_offset > caret_min_offset && caret_offset < caret_max_offset)
        return InlineBoxPosition(box, caret_offset);

      if (((caret_offset == caret_max_offset) ^
           (affinity == TextAffinity::kDownstream)) ||
          ((caret_offset == caret_min_offset) ^
           (affinity == TextAffinity::kUpstream)) ||
          (caret_offset == caret_max_offset && box->NextLeafChild() &&
           box->NextLeafChild()->IsLineBreak()))
        break;

      candidate = box;
    }
    if (candidate && candidate == text_layout_object->LastTextBox() &&
        affinity == TextAffinity::kDownstream) {
      box = SearchAheadForBetterMatch(text_layout_object);
      if (box)
        caret_offset = box->CaretMinOffset();
    }
    inline_box = box ? box : candidate;
  }

  if (!inline_box)
    return InlineBoxPosition(inline_box, caret_offset);

  unsigned char level = inline_box->BidiLevel();

  if (inline_box->Direction() == primary_direction) {
    if (caret_offset == inline_box->CaretRightmostOffset()) {
      InlineBox* next_box = inline_box->NextLeafChild();
      if (!next_box || next_box->BidiLevel() >= level)
        return InlineBoxPosition(inline_box, caret_offset);

      level = next_box->BidiLevel();
      InlineBox* prev_box = inline_box;
      do {
        prev_box = prev_box->PrevLeafChild();
      } while (prev_box && prev_box->BidiLevel() > level);

      // For example, abc FED 123 ^ CBA
      if (prev_box && prev_box->BidiLevel() == level)
        return InlineBoxPosition(inline_box, caret_offset);

      // For example, abc 123 ^ CBA
      while (InlineBox* next_box = inline_box->NextLeafChild()) {
        if (next_box->BidiLevel() < level)
          break;
        inline_box = next_box;
      }
      return InlineBoxPosition(inline_box, inline_box->CaretRightmostOffset());
    }

    if (IsStartOfDifferentDirection(inline_box))
      return InlineBoxPosition(inline_box, caret_offset);

    level = inline_box->PrevLeafChild()->BidiLevel();
    InlineBox* next_box = inline_box;
    do {
      next_box = next_box->NextLeafChild();
    } while (next_box && next_box->BidiLevel() > level);

    if (next_box && next_box->BidiLevel() == level)
      return InlineBoxPosition(inline_box, caret_offset);

    while (InlineBox* prev_box = inline_box->PrevLeafChild()) {
      if (prev_box->BidiLevel() < level)
        break;
      inline_box = prev_box;
    }
    return InlineBoxPosition(inline_box, inline_box->CaretLeftmostOffset());
  }

  if (caret_offset == inline_box->CaretLeftmostOffset()) {
    InlineBox* prev_box = inline_box->PrevLeafChildIgnoringLineBreak();
    if (!prev_box || prev_box->BidiLevel() < level) {
      // Left edge of a secondary run. Set to the right edge of the entire
      // run.
      while (InlineBox* next_box =
                 inline_box->NextLeafChildIgnoringLineBreak()) {
        if (next_box->BidiLevel() < level)
          break;
        inline_box = next_box;
      }
      return InlineBoxPosition(inline_box, inline_box->CaretRightmostOffset());
    }

    if (prev_box->BidiLevel() > level) {
      // Right edge of a "tertiary" run. Set to the left edge of that run.
      while (InlineBox* tertiary_box =
                 inline_box->PrevLeafChildIgnoringLineBreak()) {
        if (tertiary_box->BidiLevel() <= level)
          break;
        inline_box = tertiary_box;
      }
      return InlineBoxPosition(inline_box, inline_box->CaretLeftmostOffset());
    }
    return InlineBoxPosition(inline_box, caret_offset);
  }

  if (layout_object &&
      layout_object->Style()->GetUnicodeBidi() == UnicodeBidi::kPlaintext) {
    if (inline_box->BidiLevel() < level)
      return InlineBoxPosition(inline_box, inline_box->CaretLeftmostOffset());
    return InlineBoxPosition(inline_box, inline_box->CaretRightmostOffset());
  }

  InlineBox* next_box = inline_box->NextLeafChildIgnoringLineBreak();
  if (!next_box || next_box->BidiLevel() < level) {
    // Right edge of a secondary run. Set to the left edge of the entire
    // run.
    while (InlineBox* prev_box = inline_box->PrevLeafChildIgnoringLineBreak()) {
      if (prev_box->BidiLevel() < level)
        break;
      inline_box = prev_box;
    }
    return InlineBoxPosition(inline_box, inline_box->CaretLeftmostOffset());
  }

  if (next_box->BidiLevel() <= level)
    return InlineBoxPosition(inline_box, caret_offset);

  // Left edge of a "tertiary" run. Set to the right edge of that run.
  while (InlineBox* tertiary_box =
             inline_box->NextLeafChildIgnoringLineBreak()) {
    if (tertiary_box->BidiLevel() <= level)
      break;
    inline_box = tertiary_box;
  }
  return InlineBoxPosition(inline_box, inline_box->CaretRightmostOffset());
}

template <typename Strategy>
static InlineBoxPosition ComputeInlineBoxPositionTemplate(
    const PositionTemplate<Strategy>& position,
    TextAffinity affinity) {
  return ComputeInlineBoxPositionTemplate<Strategy>(
      position, affinity, PrimaryDirectionOf(*position.AnchorNode()));
}

InlineBoxPosition ComputeInlineBoxPosition(const Position& position,
                                           TextAffinity affinity) {
  return ComputeInlineBoxPositionTemplate<EditingStrategy>(position, affinity);
}

InlineBoxPosition ComputeInlineBoxPosition(const PositionInFlatTree& position,
                                           TextAffinity affinity) {
  return ComputeInlineBoxPositionTemplate<EditingInFlatTreeStrategy>(position,
                                                                     affinity);
}

InlineBoxPosition ComputeInlineBoxPosition(const VisiblePosition& position) {
  DCHECK(position.IsValid()) << position;
  return ComputeInlineBoxPosition(position.DeepEquivalent(),
                                  position.Affinity());
}

InlineBoxPosition ComputeInlineBoxPosition(const Position& position,
                                           TextAffinity affinity,
                                           TextDirection primary_direction) {
  return ComputeInlineBoxPositionTemplate<EditingStrategy>(position, affinity,
                                                           primary_direction);
}

InlineBoxPosition ComputeInlineBoxPosition(const PositionInFlatTree& position,
                                           TextAffinity affinity,
                                           TextDirection primary_direction) {
  return ComputeInlineBoxPositionTemplate<EditingInFlatTreeStrategy>(
      position, affinity, primary_direction);
}

template <typename Strategy>
LayoutRect LocalCaretRectOfPositionTemplate(
    const PositionWithAffinityTemplate<Strategy>& position,
    LayoutObject*& layout_object) {
  if (position.IsNull()) {
    layout_object = nullptr;
    return LayoutRect();
  }
  Node* node = position.AnchorNode();

  layout_object = node->GetLayoutObject();
  if (!layout_object)
    return LayoutRect();

  InlineBoxPosition box_position =
      ComputeInlineBoxPosition(position.GetPosition(), position.Affinity());

  if (box_position.inline_box)
    layout_object = LineLayoutAPIShim::LayoutObjectFrom(
        box_position.inline_box->GetLineLayoutItem());

  return layout_object->LocalCaretRect(box_position.inline_box,
                                       box_position.offset_in_box);
}

// This function was added because the caret rect that is calculated by
// using the line top value instead of the selection top.
template <typename Strategy>
LayoutRect LocalSelectionRectOfPositionTemplate(
    const PositionWithAffinityTemplate<Strategy>& position,
    LayoutObject*& layout_object) {
  if (position.IsNull()) {
    layout_object = nullptr;
    return LayoutRect();
  }
  Node* node = position.AnchorNode();
  layout_object = node->GetLayoutObject();
  if (!layout_object)
    return LayoutRect();

  InlineBoxPosition box_position =
      ComputeInlineBoxPosition(position.GetPosition(), position.Affinity());

  if (!box_position.inline_box)
    return LayoutRect();

  layout_object = LineLayoutAPIShim::LayoutObjectFrom(
      box_position.inline_box->GetLineLayoutItem());

  LayoutRect rect = layout_object->LocalCaretRect(box_position.inline_box,
                                                  box_position.offset_in_box);

  if (rect.IsEmpty())
    return rect;

  InlineBox* const box = box_position.inline_box;
  if (layout_object->Style()->IsHorizontalWritingMode()) {
    rect.SetY(box->Root().SelectionTop());
    rect.SetHeight(box->Root().SelectionHeight());
    return rect;
  }

  rect.SetX(box->Root().SelectionTop());
  rect.SetWidth(box->Root().SelectionHeight());
  return rect;
}

LayoutRect LocalCaretRectOfPosition(const PositionWithAffinity& position,
                                    LayoutObject*& layout_object) {
  return LocalCaretRectOfPositionTemplate<EditingStrategy>(position,
                                                           layout_object);
}

LayoutRect LocalSelectionRectOfPosition(const PositionWithAffinity& position,
                                        LayoutObject*& layout_object) {
  return LocalSelectionRectOfPositionTemplate<EditingStrategy>(position,
                                                               layout_object);
}

LayoutRect LocalCaretRectOfPosition(
    const PositionInFlatTreeWithAffinity& position,
    LayoutObject*& layout_object) {
  return LocalCaretRectOfPositionTemplate<EditingInFlatTreeStrategy>(
      position, layout_object);
}

static LayoutUnit BoundingBoxLogicalHeight(LayoutObject* o,
                                           const LayoutRect& rect) {
  return o->Style()->IsHorizontalWritingMode() ? rect.Height() : rect.Width();
}

bool HasRenderedNonAnonymousDescendantsWithHeight(LayoutObject* layout_object) {
  LayoutObject* stop = layout_object->NextInPreOrderAfterChildren();
  for (LayoutObject* o = layout_object->SlowFirstChild(); o && o != stop;
       o = o->NextInPreOrder()) {
    if (o->NonPseudoNode()) {
      if ((o->IsText() &&
           BoundingBoxLogicalHeight(o, ToLayoutText(o)->LinesBoundingBox())) ||
          (o->IsBox() && ToLayoutBox(o)->PixelSnappedLogicalHeight()) ||
          (o->IsLayoutInline() && IsEmptyInline(LineLayoutItem(o)) &&
           BoundingBoxLogicalHeight(o, ToLayoutInline(o)->LinesBoundingBox())))
        return true;
    }
  }
  return false;
}

VisiblePosition VisiblePositionForContentsPoint(const IntPoint& contents_point,
                                                LocalFrame* frame) {
  HitTestRequest request = HitTestRequest::kMove | HitTestRequest::kReadOnly |
                           HitTestRequest::kActive |
                           HitTestRequest::kIgnoreClipping;
  HitTestResult result(request, contents_point);
  frame->GetDocument()->GetLayoutViewItem().HitTest(result);

  if (Node* node = result.InnerNode()) {
    return CreateVisiblePosition(PositionRespectingEditingBoundary(
        frame->Selection().ComputeVisibleSelectionInDOMTreeDeprecated().Start(),
        result.LocalPoint(), node));
  }
  return VisiblePosition();
}

// TODO(yosin): We should use |associatedLayoutObjectOf()| in "VisibleUnits.cpp"
// where it takes |LayoutObject| from |Position|.
// Note about ::first-letter pseudo-element:
//   When an element has ::first-letter pseudo-element, first letter characters
//   are taken from |Text| node and first letter characters are considered
//   as content of <pseudo:first-letter>.
//   For following HTML,
//      <style>div::first-letter {color: red}</style>
//      <div>abc</div>
//   we have following layout tree:
//      LayoutBlockFlow {DIV} at (0,0) size 784x55
//        LayoutInline {<pseudo:first-letter>} at (0,0) size 22x53
//          LayoutTextFragment (anonymous) at (0,1) size 22x53
//            text run at (0,1) width 22: "a"
//        LayoutTextFragment {#text} at (21,30) size 16x17
//          text run at (21,30) width 16: "bc"
//  In this case, |Text::layoutObject()| for "abc" returns |LayoutTextFragment|
//  containing "bc", and it is called remaining part.
//
//  Even if |Text| node contains only first-letter characters, e.g. just "a",
//  remaining part of |LayoutTextFragment|, with |fragmentLength()| == 0, is
//  appeared in layout tree.
//
//  When |Text| node contains only first-letter characters and whitespaces, e.g.
//  "B\n", associated |LayoutTextFragment| is first-letter part instead of
//  remaining part.
//
//  Punctuation characters are considered as first-letter. For "(1)ab",
//  "(1)" are first-letter part and "ab" are remaining part.
LayoutObject* AssociatedLayoutObjectOf(const Node& node, int offset_in_node) {
  DCHECK_GE(offset_in_node, 0);
  LayoutObject* layout_object = node.GetLayoutObject();
  if (!node.IsTextNode() || !layout_object ||
      !ToLayoutText(layout_object)->IsTextFragment())
    return layout_object;
  LayoutTextFragment* layout_text_fragment =
      ToLayoutTextFragment(layout_object);
  if (!layout_text_fragment->IsRemainingTextLayoutObject()) {
    DCHECK_LE(
        static_cast<unsigned>(offset_in_node),
        layout_text_fragment->Start() + layout_text_fragment->FragmentLength());
    return layout_text_fragment;
  }
  if (layout_text_fragment->FragmentLength() &&
      static_cast<unsigned>(offset_in_node) >= layout_text_fragment->Start())
    return layout_object;
  LayoutObject* first_letter_layout_object =
      layout_text_fragment->GetFirstLetterPseudoElement()->GetLayoutObject();
  // TODO(yosin): We're not sure when |firstLetterLayoutObject| has
  // multiple child layout object.
  LayoutObject* child = first_letter_layout_object->SlowFirstChild();
  CHECK(child && child->IsText());
  DCHECK_EQ(child, first_letter_layout_object->SlowLastChild());
  return child;
}

int CaretMinOffset(const Node* node) {
  LayoutObject* layout_object = AssociatedLayoutObjectOf(*node, 0);
  return layout_object ? layout_object->CaretMinOffset() : 0;
}

int CaretMaxOffset(const Node* n) {
  return EditingStrategy::CaretMaxOffset(*n);
}

template <typename Strategy>
static bool InRenderedText(const PositionTemplate<Strategy>& position) {
  Node* const anchor_node = position.AnchorNode();
  if (!anchor_node || !anchor_node->IsTextNode())
    return false;

  const int offset_in_node = position.ComputeEditingOffset();
  LayoutObject* layout_object =
      AssociatedLayoutObjectOf(*anchor_node, offset_in_node);
  if (!layout_object)
    return false;

  LayoutText* text_layout_object = ToLayoutText(layout_object);
  const int text_offset =
      offset_in_node - text_layout_object->TextStartOffset();
  for (InlineTextBox* box = text_layout_object->FirstTextBox(); box;
       box = box->NextTextBox()) {
    if (text_offset < static_cast<int>(box->Start()) &&
        !text_layout_object->ContainsReversedText()) {
      // The offset we're looking for is before this node
      // this means the offset must be in content that is
      // not laid out. Return false.
      return false;
    }
    if (box->ContainsCaretOffset(text_offset)) {
      // Return false for offsets inside composed characters.
      return text_offset == text_layout_object->CaretMinOffset() ||
             text_offset == NextGraphemeBoundaryOf(
                                anchor_node, PreviousGraphemeBoundaryOf(
                                                 anchor_node, text_offset));
    }
  }

  return false;
}

bool RendersInDifferentPosition(const Position& position1,
                                const Position& position2) {
  if (position1.IsNull() || position2.IsNull())
    return false;
  LayoutObject* layout_object1;
  const LayoutRect& rect1 =
      LocalCaretRectOfPosition(PositionWithAffinity(position1), layout_object1);
  LayoutObject* layout_object2;
  const LayoutRect& rect2 =
      LocalCaretRectOfPosition(PositionWithAffinity(position2), layout_object2);
  if (!layout_object1 || !layout_object2)
    return layout_object1 != layout_object2;
  return layout_object1->LocalToAbsoluteQuad(FloatRect(rect1)) !=
         layout_object2->LocalToAbsoluteQuad(FloatRect(rect2));
}

static bool IsVisuallyEmpty(const LayoutObject* layout) {
  for (LayoutObject* child = layout->SlowFirstChild(); child;
       child = child->NextSibling()) {
    // TODO(xiaochengh): Replace type-based conditioning by virtual function.
    if (child->IsBox()) {
      if (!ToLayoutBox(child)->Size().IsEmpty())
        return false;
    } else if (child->IsLayoutInline()) {
      if (ToLayoutInline(child)->FirstLineBoxIncludingCulling())
        return false;
    } else if (child->IsText()) {
      if (ToLayoutText(child)->HasTextBoxes())
        return false;
    } else {
      return false;
    }
  }
  return true;
}

// FIXME: Share code with isCandidate, if possible.
bool EndsOfNodeAreVisuallyDistinctPositions(const Node* node) {
  if (!node || !node->GetLayoutObject())
    return false;

  if (!node->GetLayoutObject()->IsInline())
    return true;

  // Don't include inline tables.
  if (isHTMLTableElement(*node))
    return false;

  // A Marquee elements are moving so we should assume their ends are always
  // visibily distinct.
  if (isHTMLMarqueeElement(*node))
    return true;

  // There is a VisiblePosition inside an empty inline-block container.
  return node->GetLayoutObject()->IsAtomicInlineLevel() &&
         CanHaveChildrenForEditing(node) &&
         !ToLayoutBox(node->GetLayoutObject())->Size().IsEmpty() &&
         IsVisuallyEmpty(node->GetLayoutObject());
}

template <typename Strategy>
static Node* EnclosingVisualBoundary(Node* node) {
  while (node && !EndsOfNodeAreVisuallyDistinctPositions(node))
    node = Strategy::Parent(*node);

  return node;
}

// upstream() and downstream() want to return positions that are either in a
// text node or at just before a non-text node.  This method checks for that.
template <typename Strategy>
static bool IsStreamer(const PositionIteratorAlgorithm<Strategy>& pos) {
  if (!pos.GetNode())
    return true;

  if (IsAtomicNode(pos.GetNode()))
    return true;

  return pos.AtStartOfNode();
}

template <typename Strategy>
static PositionTemplate<Strategy> AdjustPositionForBackwardIteration(
    const PositionTemplate<Strategy>& position) {
  DCHECK(!position.IsNull());
  if (!position.IsAfterAnchor())
    return position;
  if (IsUserSelectContain(*position.AnchorNode()))
    return position.ToOffsetInAnchor();
  return PositionTemplate<Strategy>::EditingPositionOf(
      position.AnchorNode(), Strategy::CaretMaxOffset(*position.AnchorNode()));
}

template <typename Strategy>
static PositionTemplate<Strategy> MostBackwardCaretPosition(
    const PositionTemplate<Strategy>& position,
    EditingBoundaryCrossingRule rule) {
  DCHECK(!NeedsLayoutTreeUpdate(position)) << position;
  TRACE_EVENT0("input", "VisibleUnits::mostBackwardCaretPosition");

  Node* start_node = position.AnchorNode();
  if (!start_node)
    return PositionTemplate<Strategy>();

  // iterate backward from there, looking for a qualified position
  Node* boundary = EnclosingVisualBoundary<Strategy>(start_node);
  // FIXME: PositionIterator should respect Before and After positions.
  PositionIteratorAlgorithm<Strategy> last_visible(
      AdjustPositionForBackwardIteration<Strategy>(position));
  PositionIteratorAlgorithm<Strategy> current_pos = last_visible;
  bool start_editable = HasEditableStyle(*start_node);
  Node* last_node = start_node;
  bool boundary_crossed = false;
  for (; !current_pos.AtStart(); current_pos.Decrement()) {
    Node* current_node = current_pos.GetNode();
    // Don't check for an editability change if we haven't moved to a different
    // node, to avoid the expense of computing hasEditableStyle().
    if (current_node != last_node) {
      // Don't change editability.
      bool current_editable = HasEditableStyle(*current_node);
      if (start_editable != current_editable) {
        if (rule == kCannotCrossEditingBoundary)
          break;
        boundary_crossed = true;
      }
      last_node = current_node;
    }

    // If we've moved to a position that is visually distinct, return the last
    // saved position. There is code below that terminates early if we're
    // *about* to move to a visually distinct position.
    if (EndsOfNodeAreVisuallyDistinctPositions(current_node) &&
        current_node != boundary)
      return last_visible.DeprecatedComputePosition();

    // skip position in non-laid out or invisible node
    LayoutObject* layout_object =
        AssociatedLayoutObjectOf(*current_node, current_pos.OffsetInLeafNode());
    if (!layout_object ||
        layout_object->Style()->Visibility() != EVisibility::kVisible)
      continue;

    if (rule == kCanCrossEditingBoundary && boundary_crossed) {
      last_visible = current_pos;
      break;
    }

    // track last visible streamer position
    if (IsStreamer<Strategy>(current_pos))
      last_visible = current_pos;

    // Don't move past a position that is visually distinct.  We could rely on
    // code above to terminate and return lastVisible on the next iteration, but
    // we terminate early to avoid doing a nodeIndex() call.
    if (EndsOfNodeAreVisuallyDistinctPositions(current_node) &&
        current_pos.AtStartOfNode())
      return last_visible.DeprecatedComputePosition();

    // Return position after tables and nodes which have content that can be
    // ignored.
    if (EditingIgnoresContent(*current_node) ||
        IsDisplayInsideTable(current_node)) {
      if (current_pos.AtEndOfNode())
        return PositionTemplate<Strategy>::AfterNode(current_node);
      continue;
    }

    // return current position if it is in laid out text
    if (layout_object->IsText() &&
        ToLayoutText(layout_object)->FirstTextBox()) {
      LayoutText* const text_layout_object = ToLayoutText(layout_object);
      const unsigned text_start_offset = text_layout_object->TextStartOffset();
      if (current_node != start_node) {
        // This assertion fires in layout tests in the case-transform.html test
        // because of a mix-up between offsets in the text in the DOM tree with
        // text in the layout tree which can have a different length due to case
        // transformation.
        // Until we resolve that, disable this so we can run the layout tests!
        // DCHECK_GE(currentOffset, layoutObject->caretMaxOffset());
        return PositionTemplate<Strategy>(
            current_node, layout_object->CaretMaxOffset() + text_start_offset);
      }

      // Map offset in DOM node to offset in InlineBox.
      DCHECK_GE(current_pos.OffsetInLeafNode(),
                static_cast<int>(text_start_offset));
      const unsigned text_offset =
          current_pos.OffsetInLeafNode() - text_start_offset;
      InlineTextBox* last_text_box = text_layout_object->LastTextBox();
      for (InlineTextBox* box = text_layout_object->FirstTextBox(); box;
           box = box->NextTextBox()) {
        if (text_offset == box->Start()) {
          if (text_layout_object->IsTextFragment() &&
              ToLayoutTextFragment(layout_object)
                  ->IsRemainingTextLayoutObject()) {
            // |currentPos| is at start of remaining text of
            // |Text| node with :first-letter.
            DCHECK_GE(current_pos.OffsetInLeafNode(), 1);
            LayoutObject* first_letter_layout_object =
                ToLayoutTextFragment(layout_object)
                    ->GetFirstLetterPseudoElement()
                    ->GetLayoutObject();
            if (first_letter_layout_object &&
                first_letter_layout_object->Style()->Visibility() ==
                    EVisibility::kVisible)
              return current_pos.ComputePosition();
          }
          continue;
        }
        if (text_offset <= box->Start() + box->Len()) {
          if (text_offset > box->Start())
            return current_pos.ComputePosition();
          continue;
        }

        if (box == last_text_box ||
            text_offset != box->Start() + box->Len() + 1)
          continue;

        // The text continues on the next line only if the last text box is not
        // on this line and none of the boxes on this line have a larger start
        // offset.

        bool continues_on_next_line = true;
        InlineBox* other_box = box;
        while (continues_on_next_line) {
          other_box = other_box->NextLeafChild();
          if (!other_box)
            break;
          if (other_box == last_text_box ||
              (LineLayoutAPIShim::LayoutObjectFrom(
                   other_box->GetLineLayoutItem()) == text_layout_object &&
               ToInlineTextBox(other_box)->Start() > text_offset))
            continues_on_next_line = false;
        }

        other_box = box;
        while (continues_on_next_line) {
          other_box = other_box->PrevLeafChild();
          if (!other_box)
            break;
          if (other_box == last_text_box ||
              (LineLayoutAPIShim::LayoutObjectFrom(
                   other_box->GetLineLayoutItem()) == text_layout_object &&
               ToInlineTextBox(other_box)->Start() > text_offset))
            continues_on_next_line = false;
        }

        if (continues_on_next_line)
          return current_pos.ComputePosition();
      }
    }
  }
  return last_visible.DeprecatedComputePosition();
}

Position MostBackwardCaretPosition(const Position& position,
                                   EditingBoundaryCrossingRule rule) {
  return MostBackwardCaretPosition<EditingStrategy>(position, rule);
}

PositionInFlatTree MostBackwardCaretPosition(const PositionInFlatTree& position,
                                             EditingBoundaryCrossingRule rule) {
  return MostBackwardCaretPosition<EditingInFlatTreeStrategy>(position, rule);
}

template <typename Strategy>
PositionTemplate<Strategy> MostForwardCaretPosition(
    const PositionTemplate<Strategy>& position,
    EditingBoundaryCrossingRule rule) {
  DCHECK(!NeedsLayoutTreeUpdate(position)) << position;
  TRACE_EVENT0("input", "VisibleUnits::mostForwardCaretPosition");

  Node* start_node = position.AnchorNode();
  if (!start_node)
    return PositionTemplate<Strategy>();

  // iterate forward from there, looking for a qualified position
  Node* boundary = EnclosingVisualBoundary<Strategy>(start_node);
  // FIXME: PositionIterator should respect Before and After positions.
  PositionIteratorAlgorithm<Strategy> last_visible(
      position.IsAfterAnchor()
          ? PositionTemplate<Strategy>::EditingPositionOf(
                position.AnchorNode(),
                Strategy::CaretMaxOffset(*position.AnchorNode()))
          : position);
  PositionIteratorAlgorithm<Strategy> current_pos = last_visible;
  bool start_editable = HasEditableStyle(*start_node);
  Node* last_node = start_node;
  bool boundary_crossed = false;
  for (; !current_pos.AtEnd(); current_pos.Increment()) {
    Node* current_node = current_pos.GetNode();
    // Don't check for an editability change if we haven't moved to a different
    // node, to avoid the expense of computing hasEditableStyle().
    if (current_node != last_node) {
      // Don't change editability.
      bool current_editable = HasEditableStyle(*current_node);
      if (start_editable != current_editable) {
        if (rule == kCannotCrossEditingBoundary)
          break;
        boundary_crossed = true;
      }

      last_node = current_node;
    }

    // stop before going above the body, up into the head
    // return the last visible streamer position
    if (isHTMLBodyElement(*current_node) && current_pos.AtEndOfNode())
      break;

    // Do not move to a visually distinct position.
    if (EndsOfNodeAreVisuallyDistinctPositions(current_node) &&
        current_node != boundary)
      return last_visible.DeprecatedComputePosition();
    // Do not move past a visually disinct position.
    // Note: The first position after the last in a node whose ends are visually
    // distinct positions will be [boundary->parentNode(),
    // originalBlock->nodeIndex() + 1].
    if (boundary && Strategy::Parent(*boundary) == current_node)
      return last_visible.DeprecatedComputePosition();

    // skip position in non-laid out or invisible node
    LayoutObject* layout_object =
        AssociatedLayoutObjectOf(*current_node, current_pos.OffsetInLeafNode());
    if (!layout_object ||
        layout_object->Style()->Visibility() != EVisibility::kVisible)
      continue;

    if (rule == kCanCrossEditingBoundary && boundary_crossed) {
      last_visible = current_pos;
      break;
    }

    // track last visible streamer position
    if (IsStreamer<Strategy>(current_pos))
      last_visible = current_pos;

    // Return position before tables and nodes which have content that can be
    // ignored.
    if (EditingIgnoresContent(*current_node) ||
        IsDisplayInsideTable(current_node)) {
      if (current_pos.OffsetInLeafNode() <= layout_object->CaretMinOffset())
        return PositionTemplate<Strategy>::EditingPositionOf(
            current_node, layout_object->CaretMinOffset());
      continue;
    }

    // return current position if it is in laid out text
    if (layout_object->IsText() &&
        ToLayoutText(layout_object)->FirstTextBox()) {
      LayoutText* const text_layout_object = ToLayoutText(layout_object);
      const unsigned text_start_offset = text_layout_object->TextStartOffset();
      if (current_node != start_node) {
        DCHECK(current_pos.AtStartOfNode());
        return PositionTemplate<Strategy>(
            current_node, layout_object->CaretMinOffset() + text_start_offset);
      }

      // Map offset in DOM node to offset in InlineBox.
      DCHECK_GE(current_pos.OffsetInLeafNode(),
                static_cast<int>(text_start_offset));
      const unsigned text_offset =
          current_pos.OffsetInLeafNode() - text_start_offset;
      InlineTextBox* last_text_box = text_layout_object->LastTextBox();
      for (InlineTextBox* box = text_layout_object->FirstTextBox(); box;
           box = box->NextTextBox()) {
        if (text_offset <= box->end()) {
          if (text_offset >= box->Start())
            return current_pos.ComputePosition();
          continue;
        }

        if (box == last_text_box || text_offset != box->Start() + box->Len())
          continue;

        // The text continues on the next line only if the last text box is not
        // on this line and none of the boxes on this line have a larger start
        // offset.

        bool continues_on_next_line = true;
        InlineBox* other_box = box;
        while (continues_on_next_line) {
          other_box = other_box->NextLeafChild();
          if (!other_box)
            break;
          if (other_box == last_text_box ||
              (LineLayoutAPIShim::LayoutObjectFrom(
                   other_box->GetLineLayoutItem()) == text_layout_object &&
               ToInlineTextBox(other_box)->Start() >= text_offset))
            continues_on_next_line = false;
        }

        other_box = box;
        while (continues_on_next_line) {
          other_box = other_box->PrevLeafChild();
          if (!other_box)
            break;
          if (other_box == last_text_box ||
              (LineLayoutAPIShim::LayoutObjectFrom(
                   other_box->GetLineLayoutItem()) == text_layout_object &&
               ToInlineTextBox(other_box)->Start() >= text_offset))
            continues_on_next_line = false;
        }

        if (continues_on_next_line)
          return current_pos.ComputePosition();
      }
    }
  }

  return last_visible.DeprecatedComputePosition();
}

Position MostForwardCaretPosition(const Position& position,
                                  EditingBoundaryCrossingRule rule) {
  return MostForwardCaretPosition<EditingStrategy>(position, rule);
}

PositionInFlatTree MostForwardCaretPosition(const PositionInFlatTree& position,
                                            EditingBoundaryCrossingRule rule) {
  return MostForwardCaretPosition<EditingInFlatTreeStrategy>(position, rule);
}

// Returns true if the visually equivalent positions around have different
// editability. A position is considered at editing boundary if one of the
// following is true:
// 1. It is the first position in the node and the next visually equivalent
//    position is non editable.
// 2. It is the last position in the node and the previous visually equivalent
//    position is non editable.
// 3. It is an editable position and both the next and previous visually
//    equivalent positions are both non editable.
template <typename Strategy>
static bool AtEditingBoundary(const PositionTemplate<Strategy> positions) {
  PositionTemplate<Strategy> next_position =
      MostForwardCaretPosition(positions, kCanCrossEditingBoundary);
  if (positions.AtFirstEditingPositionForNode() && next_position.IsNotNull() &&
      !HasEditableStyle(*next_position.AnchorNode()))
    return true;

  PositionTemplate<Strategy> prev_position =
      MostBackwardCaretPosition(positions, kCanCrossEditingBoundary);
  if (positions.AtLastEditingPositionForNode() && prev_position.IsNotNull() &&
      !HasEditableStyle(*prev_position.AnchorNode()))
    return true;

  return next_position.IsNotNull() &&
         !HasEditableStyle(*next_position.AnchorNode()) &&
         prev_position.IsNotNull() &&
         !HasEditableStyle(*prev_position.AnchorNode());
}

template <typename Strategy>
static bool IsVisuallyEquivalentCandidateAlgorithm(
    const PositionTemplate<Strategy>& position) {
  Node* const anchor_node = position.AnchorNode();
  if (!anchor_node)
    return false;

  LayoutObject* layout_object = anchor_node->GetLayoutObject();
  if (!layout_object)
    return false;

  if (layout_object->Style()->Visibility() != EVisibility::kVisible)
    return false;

  if (layout_object->IsBR()) {
    // TODO(leviw) The condition should be
    // m_anchorType == PositionAnchorType::BeforeAnchor, but for now we
    // still need to support legacy positions.
    if (position.IsAfterAnchor())
      return false;
    if (position.ComputeEditingOffset())
      return false;
    const Node* parent = Strategy::Parent(*anchor_node);
    return parent->GetLayoutObject() &&
           parent->GetLayoutObject()->IsSelectable();
  }

  if (layout_object->IsText())
    return layout_object->IsSelectable() && InRenderedText(position);

  if (layout_object->IsSVG()) {
    // We don't consider SVG elements are contenteditable except for
    // associated |layoutObject| returns |isText()| true,
    // e.g. |LayoutSVGInlineText|.
    return false;
  }

  if (IsDisplayInsideTable(anchor_node) ||
      EditingIgnoresContent(*anchor_node)) {
    if (!position.AtFirstEditingPositionForNode() &&
        !position.AtLastEditingPositionForNode())
      return false;
    const Node* parent = Strategy::Parent(*anchor_node);
    return parent->GetLayoutObject() &&
           parent->GetLayoutObject()->IsSelectable();
  }

  if (anchor_node->GetDocument().documentElement() == anchor_node ||
      anchor_node->IsDocumentNode())
    return false;

  if (!layout_object->IsSelectable())
    return false;

  if (layout_object->IsLayoutBlockFlow() || layout_object->IsFlexibleBox() ||
      layout_object->IsLayoutGrid()) {
    if (ToLayoutBlock(layout_object)->LogicalHeight() ||
        isHTMLBodyElement(*anchor_node)) {
      if (!HasRenderedNonAnonymousDescendantsWithHeight(layout_object))
        return position.AtFirstEditingPositionForNode();
      return HasEditableStyle(*anchor_node) && AtEditingBoundary(position);
    }
  } else {
    return HasEditableStyle(*anchor_node) && AtEditingBoundary(position);
  }

  return false;
}

bool IsVisuallyEquivalentCandidate(const Position& position) {
  return IsVisuallyEquivalentCandidateAlgorithm<EditingStrategy>(position);
}

bool IsVisuallyEquivalentCandidate(const PositionInFlatTree& position) {
  return IsVisuallyEquivalentCandidateAlgorithm<EditingInFlatTreeStrategy>(
      position);
}

template <typename Strategy>
static IntRect AbsoluteCaretBoundsOfAlgorithm(
    const VisiblePositionTemplate<Strategy>& visible_position) {
  DCHECK(visible_position.IsValid()) << visible_position;
  LayoutObject* layout_object;
  LayoutRect local_rect = LocalCaretRectOfPosition(
      visible_position.ToPositionWithAffinity(), layout_object);
  if (local_rect.IsEmpty() || !layout_object)
    return IntRect();

  return layout_object->LocalToAbsoluteQuad(FloatRect(local_rect))
      .EnclosingBoundingBox();
}

IntRect AbsoluteCaretBoundsOf(const VisiblePosition& visible_position) {
  return AbsoluteCaretBoundsOfAlgorithm<EditingStrategy>(visible_position);
}

template <typename Strategy>
static IntRect AbsoluteSelectionBoundsOfAlgorithm(
    const VisiblePositionTemplate<Strategy>& visible_position) {
  DCHECK(visible_position.IsValid()) << visible_position;
  LayoutObject* layout_object;
  LayoutRect local_rect = LocalSelectionRectOfPosition(
      visible_position.ToPositionWithAffinity(), layout_object);
  if (local_rect.IsEmpty() || !layout_object)
    return IntRect();

  return layout_object->LocalToAbsoluteQuad(FloatRect(local_rect))
      .EnclosingBoundingBox();
}

IntRect AbsoluteSelectionBoundsOf(const VisiblePosition& visible_position) {
  return AbsoluteSelectionBoundsOfAlgorithm<EditingStrategy>(visible_position);
}

IntRect AbsoluteCaretBoundsOf(
    const VisiblePositionInFlatTree& visible_position) {
  return AbsoluteCaretBoundsOfAlgorithm<EditingInFlatTreeStrategy>(
      visible_position);
}

template <typename Strategy>
static VisiblePositionTemplate<Strategy> SkipToEndOfEditingBoundary(
    const VisiblePositionTemplate<Strategy>& pos,
    const PositionTemplate<Strategy>& anchor) {
  DCHECK(pos.IsValid()) << pos;
  if (pos.IsNull())
    return pos;

  ContainerNode* highest_root = HighestEditableRoot(anchor);
  ContainerNode* highest_root_of_pos =
      HighestEditableRoot(pos.DeepEquivalent());

  // Return |pos| itself if the two are from the very same editable region,
  // or both are non-editable.
  if (highest_root_of_pos == highest_root)
    return pos;

  // If this is not editable but |pos| has an editable root, skip to the end
  if (!highest_root && highest_root_of_pos)
    return CreateVisiblePosition(
        PositionTemplate<Strategy>(highest_root_of_pos,
                                   PositionAnchorType::kAfterAnchor)
            .ParentAnchoredEquivalent());

  // That must mean that |pos| is not editable. Return the next position after
  // |pos| that is in the same editable region as this position
  DCHECK(highest_root);
  return FirstEditableVisiblePositionAfterPositionInRoot(pos.DeepEquivalent(),
                                                         *highest_root);
}

template <typename Strategy>
static UChar32 CharacterAfterAlgorithm(
    const VisiblePositionTemplate<Strategy>& visible_position) {
  DCHECK(visible_position.IsValid()) << visible_position;
  // We canonicalize to the first of two equivalent candidates, but the second
  // of the two candidates is the one that will be inside the text node
  // containing the character after this visible position.
  const PositionTemplate<Strategy> pos =
      MostForwardCaretPosition(visible_position.DeepEquivalent());
  if (!pos.IsOffsetInAnchor())
    return 0;
  Node* container_node = pos.ComputeContainerNode();
  if (!container_node || !container_node->IsTextNode())
    return 0;
  unsigned offset = static_cast<unsigned>(pos.OffsetInContainerNode());
  Text* text_node = ToText(container_node);
  unsigned length = text_node->length();
  if (offset >= length)
    return 0;

  return text_node->data().CharacterStartingAt(offset);
}

UChar32 CharacterAfter(const VisiblePosition& visible_position) {
  return CharacterAfterAlgorithm<EditingStrategy>(visible_position);
}

UChar32 CharacterAfter(const VisiblePositionInFlatTree& visible_position) {
  return CharacterAfterAlgorithm<EditingInFlatTreeStrategy>(visible_position);
}

template <typename Strategy>
static UChar32 CharacterBeforeAlgorithm(
    const VisiblePositionTemplate<Strategy>& visible_position) {
  DCHECK(visible_position.IsValid()) << visible_position;
  return CharacterAfter(PreviousPositionOf(visible_position));
}

UChar32 CharacterBefore(const VisiblePosition& visible_position) {
  return CharacterBeforeAlgorithm<EditingStrategy>(visible_position);
}

UChar32 CharacterBefore(const VisiblePositionInFlatTree& visible_position) {
  return CharacterBeforeAlgorithm<EditingInFlatTreeStrategy>(visible_position);
}

template <typename Strategy>
static PositionTemplate<Strategy> LeftVisuallyDistinctCandidate(
    const VisiblePositionTemplate<Strategy>& visible_position) {
  DCHECK(visible_position.IsValid()) << visible_position;
  const PositionTemplate<Strategy> deep_position =
      visible_position.DeepEquivalent();
  PositionTemplate<Strategy> p = deep_position;

  if (p.IsNull())
    return PositionTemplate<Strategy>();

  const PositionTemplate<Strategy> downstream_start =
      MostForwardCaretPosition(p);
  TextDirection primary_direction = PrimaryDirectionOf(*p.AnchorNode());
  const TextAffinity affinity = visible_position.Affinity();

  while (true) {
    InlineBoxPosition box_position =
        ComputeInlineBoxPosition(p, affinity, primary_direction);
    InlineBox* box = box_position.inline_box;
    int offset = box_position.offset_in_box;
    if (!box)
      return primary_direction == TextDirection::kLtr
                 ? PreviousVisuallyDistinctCandidate(deep_position)
                 : NextVisuallyDistinctCandidate(deep_position);

    LineLayoutItem line_layout_item = box->GetLineLayoutItem();

    while (true) {
      if ((line_layout_item.IsAtomicInlineLevel() || line_layout_item.IsBR()) &&
          offset == box->CaretRightmostOffset())
        return box->IsLeftToRightDirection()
                   ? PreviousVisuallyDistinctCandidate(deep_position)
                   : NextVisuallyDistinctCandidate(deep_position);

      if (!line_layout_item.GetNode()) {
        box = box->PrevLeafChild();
        if (!box)
          return primary_direction == TextDirection::kLtr
                     ? PreviousVisuallyDistinctCandidate(deep_position)
                     : NextVisuallyDistinctCandidate(deep_position);
        line_layout_item = box->GetLineLayoutItem();
        offset = box->CaretRightmostOffset();
        continue;
      }

      offset =
          box->IsLeftToRightDirection()
              ? PreviousGraphemeBoundaryOf(line_layout_item.GetNode(), offset)
              : NextGraphemeBoundaryOf(line_layout_item.GetNode(), offset);

      int caret_min_offset = box->CaretMinOffset();
      int caret_max_offset = box->CaretMaxOffset();

      if (offset > caret_min_offset && offset < caret_max_offset)
        break;

      if (box->IsLeftToRightDirection() ? offset < caret_min_offset
                                        : offset > caret_max_offset) {
        // Overshot to the left.
        InlineBox* prev_box = box->PrevLeafChildIgnoringLineBreak();
        if (!prev_box) {
          PositionTemplate<Strategy> position_on_left =
              primary_direction == TextDirection::kLtr
                  ? PreviousVisuallyDistinctCandidate(
                        visible_position.DeepEquivalent())
                  : NextVisuallyDistinctCandidate(
                        visible_position.DeepEquivalent());
          if (position_on_left.IsNull())
            return PositionTemplate<Strategy>();

          InlineBox* box_on_left =
              ComputeInlineBoxPosition(position_on_left, affinity,
                                       primary_direction)
                  .inline_box;
          if (box_on_left && box_on_left->Root() == box->Root())
            return PositionTemplate<Strategy>();
          return position_on_left;
        }

        // Reposition at the other logical position corresponding to our
        // edge's visual position and go for another round.
        box = prev_box;
        line_layout_item = box->GetLineLayoutItem();
        offset = prev_box->CaretRightmostOffset();
        continue;
      }

      DCHECK_EQ(offset, box->CaretLeftmostOffset());

      unsigned char level = box->BidiLevel();
      InlineBox* prev_box = box->PrevLeafChild();

      if (box->Direction() == primary_direction) {
        if (!prev_box) {
          InlineBox* logical_start = 0;
          if (primary_direction == TextDirection::kLtr
                  ? box->Root().GetLogicalStartBoxWithNode(logical_start)
                  : box->Root().GetLogicalEndBoxWithNode(logical_start)) {
            box = logical_start;
            line_layout_item = box->GetLineLayoutItem();
            offset = primary_direction == TextDirection::kLtr
                         ? box->CaretMinOffset()
                         : box->CaretMaxOffset();
          }
          break;
        }
        if (prev_box->BidiLevel() >= level)
          break;

        level = prev_box->BidiLevel();

        InlineBox* next_box = box;
        do {
          next_box = next_box->NextLeafChild();
        } while (next_box && next_box->BidiLevel() > level);

        if (next_box && next_box->BidiLevel() == level)
          break;

        box = prev_box;
        line_layout_item = box->GetLineLayoutItem();
        offset = box->CaretRightmostOffset();
        if (box->Direction() == primary_direction)
          break;
        continue;
      }

      while (prev_box && !prev_box->GetLineLayoutItem().GetNode())
        prev_box = prev_box->PrevLeafChild();

      if (prev_box) {
        box = prev_box;
        line_layout_item = box->GetLineLayoutItem();
        offset = box->CaretRightmostOffset();
        if (box->BidiLevel() > level) {
          do {
            prev_box = prev_box->PrevLeafChild();
          } while (prev_box && prev_box->BidiLevel() > level);

          if (!prev_box || prev_box->BidiLevel() < level)
            continue;
        }
      } else {
        // Trailing edge of a secondary run. Set to the leading edge of
        // the entire run.
        while (true) {
          while (InlineBox* next_box = box->NextLeafChild()) {
            if (next_box->BidiLevel() < level)
              break;
            box = next_box;
          }
          if (box->BidiLevel() == level)
            break;
          level = box->BidiLevel();
          while (InlineBox* prev_box = box->PrevLeafChild()) {
            if (prev_box->BidiLevel() < level)
              break;
            box = prev_box;
          }
          if (box->BidiLevel() == level)
            break;
          level = box->BidiLevel();
        }
        line_layout_item = box->GetLineLayoutItem();
        offset = primary_direction == TextDirection::kLtr
                     ? box->CaretMinOffset()
                     : box->CaretMaxOffset();
      }
      break;
    }

    p = PositionTemplate<Strategy>::EditingPositionOf(
        line_layout_item.GetNode(), offset);

    if ((IsVisuallyEquivalentCandidate(p) &&
         MostForwardCaretPosition(p) != downstream_start) ||
        p.AtStartOfTree() || p.AtEndOfTree())
      return p;

    DCHECK_NE(p, deep_position);
  }
}

template <typename Strategy>
VisiblePositionTemplate<Strategy> LeftPositionOfAlgorithm(
    const VisiblePositionTemplate<Strategy>& visible_position) {
  DCHECK(visible_position.IsValid()) << visible_position;
  const PositionTemplate<Strategy> pos =
      LeftVisuallyDistinctCandidate(visible_position);
  // TODO(yosin) Why can't we move left from the last position in a tree?
  if (pos.AtStartOfTree() || pos.AtEndOfTree())
    return VisiblePositionTemplate<Strategy>();

  const VisiblePositionTemplate<Strategy> left = CreateVisiblePosition(pos);
  DCHECK_NE(left.DeepEquivalent(), visible_position.DeepEquivalent());

  return DirectionOfEnclosingBlock(left.DeepEquivalent()) == TextDirection::kLtr
             ? HonorEditingBoundaryAtOrBefore(left,
                                              visible_position.DeepEquivalent())
             : HonorEditingBoundaryAtOrAfter(left,
                                             visible_position.DeepEquivalent());
}

VisiblePosition LeftPositionOf(const VisiblePosition& visible_position) {
  return LeftPositionOfAlgorithm<EditingStrategy>(visible_position);
}

VisiblePositionInFlatTree LeftPositionOf(
    const VisiblePositionInFlatTree& visible_position) {
  return LeftPositionOfAlgorithm<EditingInFlatTreeStrategy>(visible_position);
}

template <typename Strategy>
static PositionTemplate<Strategy> RightVisuallyDistinctCandidate(
    const VisiblePositionTemplate<Strategy>& visible_position) {
  DCHECK(visible_position.IsValid()) << visible_position;
  const PositionTemplate<Strategy> deep_position =
      visible_position.DeepEquivalent();
  PositionTemplate<Strategy> p = deep_position;
  if (p.IsNull())
    return PositionTemplate<Strategy>();

  const PositionTemplate<Strategy> downstream_start =
      MostForwardCaretPosition(p);
  TextDirection primary_direction = PrimaryDirectionOf(*p.AnchorNode());
  const TextAffinity affinity = visible_position.Affinity();

  while (true) {
    InlineBoxPosition box_position =
        ComputeInlineBoxPosition(p, affinity, primary_direction);
    InlineBox* box = box_position.inline_box;
    int offset = box_position.offset_in_box;
    if (!box)
      return primary_direction == TextDirection::kLtr
                 ? NextVisuallyDistinctCandidate(deep_position)
                 : PreviousVisuallyDistinctCandidate(deep_position);

    LayoutObject* layout_object =
        LineLayoutAPIShim::LayoutObjectFrom(box->GetLineLayoutItem());

    while (true) {
      if ((layout_object->IsAtomicInlineLevel() || layout_object->IsBR()) &&
          offset == box->CaretLeftmostOffset())
        return box->IsLeftToRightDirection()
                   ? NextVisuallyDistinctCandidate(deep_position)
                   : PreviousVisuallyDistinctCandidate(deep_position);

      if (!layout_object->GetNode()) {
        box = box->NextLeafChild();
        if (!box)
          return primary_direction == TextDirection::kLtr
                     ? NextVisuallyDistinctCandidate(deep_position)
                     : PreviousVisuallyDistinctCandidate(deep_position);
        layout_object =
            LineLayoutAPIShim::LayoutObjectFrom(box->GetLineLayoutItem());
        offset = box->CaretLeftmostOffset();
        continue;
      }

      offset =
          box->IsLeftToRightDirection()
              ? NextGraphemeBoundaryOf(layout_object->GetNode(), offset)
              : PreviousGraphemeBoundaryOf(layout_object->GetNode(), offset);

      int caret_min_offset = box->CaretMinOffset();
      int caret_max_offset = box->CaretMaxOffset();

      if (offset > caret_min_offset && offset < caret_max_offset)
        break;

      if (box->IsLeftToRightDirection() ? offset > caret_max_offset
                                        : offset < caret_min_offset) {
        // Overshot to the right.
        InlineBox* next_box = box->NextLeafChildIgnoringLineBreak();
        if (!next_box) {
          PositionTemplate<Strategy> position_on_right =
              primary_direction == TextDirection::kLtr
                  ? NextVisuallyDistinctCandidate(deep_position)
                  : PreviousVisuallyDistinctCandidate(deep_position);
          if (position_on_right.IsNull())
            return PositionTemplate<Strategy>();

          InlineBox* box_on_right =
              ComputeInlineBoxPosition(position_on_right, affinity,
                                       primary_direction)
                  .inline_box;
          if (box_on_right && box_on_right->Root() == box->Root())
            return PositionTemplate<Strategy>();
          return position_on_right;
        }

        // Reposition at the other logical position corresponding to our
        // edge's visual position and go for another round.
        box = next_box;
        layout_object =
            LineLayoutAPIShim::LayoutObjectFrom(box->GetLineLayoutItem());
        offset = next_box->CaretLeftmostOffset();
        continue;
      }

      DCHECK_EQ(offset, box->CaretRightmostOffset());

      unsigned char level = box->BidiLevel();
      InlineBox* next_box = box->NextLeafChild();

      if (box->Direction() == primary_direction) {
        if (!next_box) {
          InlineBox* logical_end = 0;
          if (primary_direction == TextDirection::kLtr
                  ? box->Root().GetLogicalEndBoxWithNode(logical_end)
                  : box->Root().GetLogicalStartBoxWithNode(logical_end)) {
            box = logical_end;
            layout_object =
                LineLayoutAPIShim::LayoutObjectFrom(box->GetLineLayoutItem());
            offset = primary_direction == TextDirection::kLtr
                         ? box->CaretMaxOffset()
                         : box->CaretMinOffset();
          }
          break;
        }

        if (next_box->BidiLevel() >= level)
          break;

        level = next_box->BidiLevel();

        InlineBox* prev_box = box;
        do {
          prev_box = prev_box->PrevLeafChild();
        } while (prev_box && prev_box->BidiLevel() > level);

        // For example, abc FED 123 ^ CBA
        if (prev_box && prev_box->BidiLevel() == level)
          break;

        // For example, abc 123 ^ CBA or 123 ^ CBA abc
        box = next_box;
        layout_object =
            LineLayoutAPIShim::LayoutObjectFrom(box->GetLineLayoutItem());
        offset = box->CaretLeftmostOffset();
        if (box->Direction() == primary_direction)
          break;
        continue;
      }

      while (next_box && !next_box->GetLineLayoutItem().GetNode())
        next_box = next_box->NextLeafChild();

      if (next_box) {
        box = next_box;
        layout_object =
            LineLayoutAPIShim::LayoutObjectFrom(box->GetLineLayoutItem());
        offset = box->CaretLeftmostOffset();

        if (box->BidiLevel() > level) {
          do {
            next_box = next_box->NextLeafChild();
          } while (next_box && next_box->BidiLevel() > level);

          if (!next_box || next_box->BidiLevel() < level)
            continue;
        }
      } else {
        // Trailing edge of a secondary run. Set to the leading edge of the
        // entire run.
        while (true) {
          while (InlineBox* prev_box = box->PrevLeafChild()) {
            if (prev_box->BidiLevel() < level)
              break;
            box = prev_box;
          }
          if (box->BidiLevel() == level)
            break;
          level = box->BidiLevel();
          while (InlineBox* next_box = box->NextLeafChild()) {
            if (next_box->BidiLevel() < level)
              break;
            box = next_box;
          }
          if (box->BidiLevel() == level)
            break;
          level = box->BidiLevel();
        }
        layout_object =
            LineLayoutAPIShim::LayoutObjectFrom(box->GetLineLayoutItem());
        offset = primary_direction == TextDirection::kLtr
                     ? box->CaretMaxOffset()
                     : box->CaretMinOffset();
      }
      break;
    }

    p = PositionTemplate<Strategy>::EditingPositionOf(layout_object->GetNode(),
                                                      offset);

    if ((IsVisuallyEquivalentCandidate(p) &&
         MostForwardCaretPosition(p) != downstream_start) ||
        p.AtStartOfTree() || p.AtEndOfTree())
      return p;

    DCHECK_NE(p, deep_position);
  }
}

template <typename Strategy>
static VisiblePositionTemplate<Strategy> RightPositionOfAlgorithm(
    const VisiblePositionTemplate<Strategy>& visible_position) {
  DCHECK(visible_position.IsValid()) << visible_position;
  const PositionTemplate<Strategy> pos =
      RightVisuallyDistinctCandidate(visible_position);
  // FIXME: Why can't we move left from the last position in a tree?
  if (pos.AtStartOfTree() || pos.AtEndOfTree())
    return VisiblePositionTemplate<Strategy>();

  const VisiblePositionTemplate<Strategy> right = CreateVisiblePosition(pos);
  DCHECK_NE(right.DeepEquivalent(), visible_position.DeepEquivalent());

  return DirectionOfEnclosingBlock(right.DeepEquivalent()) ==
                 TextDirection::kLtr
             ? HonorEditingBoundaryAtOrAfter(right,
                                             visible_position.DeepEquivalent())
             : HonorEditingBoundaryAtOrBefore(
                   right, visible_position.DeepEquivalent());
}

VisiblePosition RightPositionOf(const VisiblePosition& visible_position) {
  return RightPositionOfAlgorithm<EditingStrategy>(visible_position);
}

VisiblePositionInFlatTree RightPositionOf(
    const VisiblePositionInFlatTree& visible_position) {
  return RightPositionOfAlgorithm<EditingInFlatTreeStrategy>(visible_position);
}

template <typename Strategy>
static VisiblePositionTemplate<Strategy> NextPositionOfAlgorithm(
    const PositionWithAffinityTemplate<Strategy>& position,
    EditingBoundaryCrossingRule rule) {
  const VisiblePositionTemplate<Strategy> next = CreateVisiblePosition(
      NextVisuallyDistinctCandidate(position.GetPosition()),
      position.Affinity());

  switch (rule) {
    case kCanCrossEditingBoundary:
      return next;
    case kCannotCrossEditingBoundary:
      return HonorEditingBoundaryAtOrAfter(next, position.GetPosition());
    case kCanSkipOverEditingBoundary:
      return SkipToEndOfEditingBoundary(next, position.GetPosition());
  }
  NOTREACHED();
  return HonorEditingBoundaryAtOrAfter(next, position.GetPosition());
}

VisiblePosition NextPositionOf(const VisiblePosition& visible_position,
                               EditingBoundaryCrossingRule rule) {
  DCHECK(visible_position.IsValid()) << visible_position;
  return NextPositionOfAlgorithm<EditingStrategy>(
      visible_position.ToPositionWithAffinity(), rule);
}

VisiblePositionInFlatTree NextPositionOf(
    const VisiblePositionInFlatTree& visible_position,
    EditingBoundaryCrossingRule rule) {
  DCHECK(visible_position.IsValid()) << visible_position;
  return NextPositionOfAlgorithm<EditingInFlatTreeStrategy>(
      visible_position.ToPositionWithAffinity(), rule);
}

template <typename Strategy>
static VisiblePositionTemplate<Strategy> SkipToStartOfEditingBoundary(
    const VisiblePositionTemplate<Strategy>& pos,
    const PositionTemplate<Strategy>& anchor) {
  DCHECK(pos.IsValid()) << pos;
  if (pos.IsNull())
    return pos;

  ContainerNode* highest_root = HighestEditableRoot(anchor);
  ContainerNode* highest_root_of_pos =
      HighestEditableRoot(pos.DeepEquivalent());

  // Return |pos| itself if the two are from the very same editable region, or
  // both are non-editable.
  if (highest_root_of_pos == highest_root)
    return pos;

  // If this is not editable but |pos| has an editable root, skip to the start
  if (!highest_root && highest_root_of_pos)
    return CreateVisiblePosition(PreviousVisuallyDistinctCandidate(
        PositionTemplate<Strategy>(highest_root_of_pos,
                                   PositionAnchorType::kBeforeAnchor)
            .ParentAnchoredEquivalent()));

  // That must mean that |pos| is not editable. Return the last position
  // before |pos| that is in the same editable region as this position
  DCHECK(highest_root);
  return LastEditableVisiblePositionBeforePositionInRoot(pos.DeepEquivalent(),
                                                         *highest_root);
}

template <typename Strategy>
static VisiblePositionTemplate<Strategy> PreviousPositionOfAlgorithm(
    const PositionTemplate<Strategy>& position,
    EditingBoundaryCrossingRule rule) {
  const PositionTemplate<Strategy> prev_position =
      PreviousVisuallyDistinctCandidate(position);

  // return null visible position if there is no previous visible position
  if (prev_position.AtStartOfTree())
    return VisiblePositionTemplate<Strategy>();

  // we should always be able to make the affinity |TextAffinity::Downstream|,
  // because going previous from an |TextAffinity::Upstream| position can
  // never yield another |TextAffinity::Upstream position| (unless line wrap
  // length is 0!).
  const VisiblePositionTemplate<Strategy> prev =
      CreateVisiblePosition(prev_position);
  if (prev.DeepEquivalent() == position)
    return VisiblePositionTemplate<Strategy>();

  switch (rule) {
    case kCanCrossEditingBoundary:
      return prev;
    case kCannotCrossEditingBoundary:
      return HonorEditingBoundaryAtOrBefore(prev, position);
    case kCanSkipOverEditingBoundary:
      return SkipToStartOfEditingBoundary(prev, position);
  }

  NOTREACHED();
  return HonorEditingBoundaryAtOrBefore(prev, position);
}

VisiblePosition PreviousPositionOf(const VisiblePosition& visible_position,
                                   EditingBoundaryCrossingRule rule) {
  DCHECK(visible_position.IsValid()) << visible_position;
  return PreviousPositionOfAlgorithm<EditingStrategy>(
      visible_position.DeepEquivalent(), rule);
}

VisiblePositionInFlatTree PreviousPositionOf(
    const VisiblePositionInFlatTree& visible_position,
    EditingBoundaryCrossingRule rule) {
  DCHECK(visible_position.IsValid()) << visible_position;
  return PreviousPositionOfAlgorithm<EditingInFlatTreeStrategy>(
      visible_position.DeepEquivalent(), rule);
}

template <typename Strategy>
static EphemeralRangeTemplate<Strategy> MakeSearchRange(
    const PositionTemplate<Strategy>& pos) {
  Node* node = pos.ComputeContainerNode();
  if (!node)
    return EphemeralRangeTemplate<Strategy>();
  Document& document = node->GetDocument();
  if (!document.documentElement())
    return EphemeralRangeTemplate<Strategy>();
  Element* boundary = EnclosingBlockFlowElement(*node);
  if (!boundary)
    return EphemeralRangeTemplate<Strategy>();

  return EphemeralRangeTemplate<Strategy>(
      pos, PositionTemplate<Strategy>::LastPositionInNode(boundary));
}

template <typename Strategy>
static PositionTemplate<Strategy> SkipWhitespaceAlgorithm(
    const PositionTemplate<Strategy>& position) {
  const EphemeralRangeTemplate<Strategy>& search_range =
      MakeSearchRange(position);
  if (search_range.IsNull())
    return position;

  CharacterIteratorAlgorithm<Strategy> char_it(
      search_range.StartPosition(), search_range.EndPosition(),
      TextIteratorBehavior::Builder()
          .SetEmitsCharactersBetweenAllVisiblePositions(true)
          .Build());
  PositionTemplate<Strategy> runner = position;
  // TODO(editing-dev): We should consider U+20E3, COMBINING ENCLOSING KEYCAP.
  // When whitespace character followed by U+20E3, we should not consider
  // it as trailing white space.
  for (; char_it.length(); char_it.Advance(1)) {
    UChar c = char_it.CharacterAt(0);
    if ((!IsSpaceOrNewline(c) && c != kNoBreakSpaceCharacter) || c == '\n')
      return runner;
    runner = char_it.EndPosition();
  }
  return runner;
}

Position SkipWhitespace(const Position& position) {
  return SkipWhitespaceAlgorithm(position);
}

PositionInFlatTree SkipWhitespace(const PositionInFlatTree& position) {
  return SkipWhitespaceAlgorithm(position);
}

static void CollectAbsoluteBoundsForRange(unsigned start,
                                          unsigned end,
                                          const LayoutText& layout_text,
                                          Vector<IntRect>& rects) {
  layout_text.AbsoluteRectsForRange(rects, start, end);
}

static void CollectAbsoluteBoundsForRange(unsigned start,
                                          unsigned end,
                                          const LayoutText& layout_text,
                                          Vector<FloatQuad>& quads) {
  layout_text.AbsoluteQuadsForRange(quads, start, end);
}

template <typename RectType>
static Vector<RectType> ComputeTextBounds(const EphemeralRange& range) {
  const Position& start_position = range.StartPosition();
  const Position& end_position = range.EndPosition();
  Node* const start_container = start_position.ComputeContainerNode();
  DCHECK(start_container);
  Node* const end_container = end_position.ComputeContainerNode();
  DCHECK(end_container);

  Vector<RectType> result;
  for (const Node& node : range.Nodes()) {
    LayoutObject* const layout_object = node.GetLayoutObject();
    if (!layout_object || !layout_object->IsText())
      continue;
    const LayoutText* layout_text = ToLayoutText(layout_object);
    unsigned start_offset =
        node == start_container ? start_position.OffsetInContainerNode() : 0;
    unsigned end_offset = node == end_container
                              ? end_position.OffsetInContainerNode()
                              : std::numeric_limits<unsigned>::max();
    CollectAbsoluteBoundsForRange(start_offset, end_offset, *layout_text,
                                  result);
  }
  return result;
}

IntRect ComputeTextRect(const EphemeralRange& range) {
  IntRect result;
  const Vector<IntRect>& rects = ComputeTextBounds<IntRect>(range);
  for (const IntRect& rect : rects)
    result.Unite(rect);
  return result;
}

Vector<FloatQuad> ComputeTextQuads(const EphemeralRange& range) {
  return ComputeTextBounds<FloatQuad>(range);
}

}  // namespace blink
