Exemplo n.º 1
0
VisibleSelectionTemplate<Strategy> PendingSelection::calcVisibleSelectionAlgorithm(const VisibleSelectionTemplate<Strategy>& originalSelection) const
{
    const PositionTemplate<Strategy> start = originalSelection.start();
    const PositionTemplate<Strategy> end = originalSelection.end();
    SelectionType selectionType = originalSelection.selectionType();
    const TextAffinity affinity = originalSelection.affinity();

    bool paintBlockCursor = m_frameSelection->shouldShowBlockCursor() && selectionType == SelectionType::CaretSelection && !isLogicalEndOfLine(createVisiblePosition(end, affinity));
    VisibleSelectionTemplate<Strategy> selection;
    if (enclosingTextFormControl(start.computeContainerNode())) {
        // TODO(yosin) We should use |PositionMoveType::Character| to avoid
        // ending paint at middle of character.
        PositionTemplate<Strategy> endPosition = paintBlockCursor ? nextPositionOf(originalSelection.extent(), PositionMoveType::CodePoint) : end;
        selection.setWithoutValidation(start, endPosition);
        return selection;
    }

    const VisiblePositionTemplate<Strategy> visibleStart = createVisiblePosition(start, selectionType == SelectionType::RangeSelection ? TextAffinity::Downstream : affinity);
    if (paintBlockCursor) {
        VisiblePositionTemplate<Strategy> visibleExtent = createVisiblePosition(end, affinity);
        visibleExtent = nextPositionOf(visibleExtent, CanSkipOverEditingBoundary);
        return VisibleSelectionTemplate<Strategy>(visibleStart, visibleExtent);
    }
    const VisiblePositionTemplate<Strategy> visibleEnd = createVisiblePosition(end, selectionType == SelectionType::RangeSelection ? TextAffinity::Upstream : affinity);
    return VisibleSelectionTemplate<Strategy>(visibleStart, visibleEnd);
}
Exemplo n.º 2
0
EphemeralRangeTemplate<Strategy> CharacterIteratorAlgorithm<Strategy>::range()
    const {
  EphemeralRangeTemplate<Strategy> range(m_textIterator.range());
  if (m_textIterator.atEnd() || m_textIterator.length() <= 1)
    return range;
  PositionTemplate<Strategy> startPosition =
      range.startPosition().parentAnchoredEquivalent();
  PositionTemplate<Strategy> endPosition =
      range.endPosition().parentAnchoredEquivalent();
  Node* node = startPosition.computeContainerNode();
  DCHECK_EQ(node, endPosition.computeContainerNode());
  int offset = startPosition.offsetInContainerNode() + m_runOffset;
  return EphemeralRangeTemplate<Strategy>(
      PositionTemplate<Strategy>(node, offset),
      PositionTemplate<Strategy>(node, offset + 1));
}
Exemplo n.º 3
0
String CreateMarkupAlgorithm<Strategy>::createMarkup(
    const PositionTemplate<Strategy>& startPosition,
    const PositionTemplate<Strategy>& endPosition,
    EAnnotateForInterchange shouldAnnotate,
    ConvertBlocksToInlines convertBlocksToInlines,
    EAbsoluteURLs shouldResolveURLs,
    Node* constrainingAncestor) {
  if (startPosition.isNull() || endPosition.isNull())
    return emptyString();

  RELEASE_ASSERT(startPosition.compareTo(endPosition) <= 0);

  bool collapsed = startPosition == endPosition;
  if (collapsed)
    return emptyString();
  Node* commonAncestor =
      Strategy::commonAncestor(*startPosition.computeContainerNode(),
                               *endPosition.computeContainerNode());
  if (!commonAncestor)
    return emptyString();

  Document* document = startPosition.document();

  DCHECK(!document->needsLayoutTreeUpdate());
  DocumentLifecycle::DisallowTransitionScope disallowTransition(
      document->lifecycle());

  HTMLElement* specialCommonAncestor = highestAncestorToWrapMarkup<Strategy>(
      startPosition, endPosition, shouldAnnotate, constrainingAncestor);
  StyledMarkupSerializer<Strategy> serializer(
      shouldResolveURLs, shouldAnnotate, startPosition, endPosition,
      specialCommonAncestor, convertBlocksToInlines);
  return serializer.createMarkup();
}
Exemplo n.º 4
0
void PendingSelection::commitAlgorithm(LayoutView& layoutView)
{
    if (!hasPendingSelection())
        return;
    ASSERT(!layoutView.needsLayout());
    m_hasPendingSelection = false;

    const VisibleSelectionTemplate<Strategy> originalSelection = m_frameSelection->visibleSelection<Strategy>();

    // Skip if pending VisibilePositions became invalid before we reach here.
    if (!isSelectionInDocument(originalSelection, layoutView.document()))
        return;

    // Construct a new VisibleSolution, since visibleSelection() is not necessarily
    // valid, and the following steps assume a valid selection.
    // See <https://bugs.webkit.org/show_bug.cgi?id=69563> and
    // <rdar://problem/10232866>.
    const VisibleSelectionTemplate<Strategy> selection = calcVisibleSelectionAlgorithm<Strategy>(originalSelection);

    if (!selection.isRange()) {
        layoutView.clearSelection();
        return;
    }

    // Use the rightmost candidate for the start of the selection, and the
    // leftmost candidate for the end of the selection. Example: foo <a>bar</a>.
    // Imagine that a line wrap occurs after 'foo', and that 'bar' is selected.
    // If we pass [foo, 3] as the start of the selection, the selection painting
    // code will think that content on the line containing 'foo' is selected
    // and will fill the gap before 'bar'.
    PositionTemplate<Strategy> startPos = selection.start();
    PositionTemplate<Strategy> candidate = mostForwardCaretPosition(startPos);
    if (isVisuallyEquivalentCandidate(candidate))
        startPos = candidate;
    PositionTemplate<Strategy> endPos = selection.end();
    candidate = mostBackwardCaretPosition(endPos);
    if (isVisuallyEquivalentCandidate(candidate))
        endPos = candidate;

    // We can get into a state where the selection endpoints map to the same
    // |VisiblePosition| when a selection is deleted because we don't yet notify
    // the |FrameSelection| of text removal.
    if (startPos.isNull() || endPos.isNull() || selection.visibleStart().deepEquivalent() == selection.visibleEnd().deepEquivalent())
        return;
    LayoutObject* startLayoutObject = startPos.anchorNode()->layoutObject();
    LayoutObject* endLayoutObject = endPos.anchorNode()->layoutObject();
    if (!startLayoutObject || !endLayoutObject)
        return;
    ASSERT(layoutView == startLayoutObject->view() && layoutView == endLayoutObject->view());
    layoutView.setSelection(startLayoutObject, startPos.computeEditingOffset(), endLayoutObject, endPos.computeEditingOffset());
}
Exemplo n.º 5
0
PositionIteratorAlgorithm<Strategy>::PositionIteratorAlgorithm(
    const PositionTemplate<Strategy>& pos)
    : PositionIteratorAlgorithm(pos.anchorNode(), pos.computeEditingOffset()) {}
Exemplo n.º 6
0
static bool isSelectionInDocument(const VisibleSelectionTemplate<Strategy>& visibleSelection, const Document& document)
{
    const PositionTemplate<Strategy> start = visibleSelection.start();
    if (start.isNotNull() && (!start.inDocument() || start.document() != document))
        return false;
    const PositionTemplate<Strategy> end = visibleSelection.end();
    if (end.isNotNull() && (!end.inDocument() || end.document() != document))
        return false;
    const PositionTemplate<Strategy> extent = visibleSelection.extent();
    if (extent.isNotNull() && (!extent.inDocument() || extent.document() != document))
        return false;
    return true;
}