Position RenderedPosition::positionAtRightBoundaryOfBiDiRun() const { ASSERT(atRightBoundaryOfBidiRun()); if (atRightmostOffsetInBox()) return createLegacyEditingPosition(m_renderer->node(), m_offset); return createLegacyEditingPosition(prevLeafChild()->renderer().node(), prevLeafChild()->caretRightmostOffset()); }
Position RenderedPosition::positionAtRightBoundaryOfBiDiRun() const { ASSERT(atRightBoundaryOfBidiRun()); if (atRightmostOffsetInBox()) return Position::editingPositionOf(m_layoutObject->node(), m_offset); return Position::editingPositionOf(prevLeafChild()->layoutObject().node(), prevLeafChild()->caretRightmostOffset()); }
InlineBox* InlineBox::prevLeafChildIgnoringLineBreak() const { InlineBox* leaf = prevLeafChild(); if (leaf && leaf->isLineBreak()) return 0; return leaf; }
bool RenderedPosition::atRightBoundaryOfBidiRun(ShouldMatchBidiLevel shouldMatchBidiLevel, unsigned char bidiLevelOfRun) const { if (!m_inlineBox) return false; if (atRightmostOffsetInBox()) { if (shouldMatchBidiLevel == IgnoreBidiLevel) return !nextLeafChild() || nextLeafChild()->bidiLevel() < m_inlineBox->bidiLevel(); return m_inlineBox->bidiLevel() >= bidiLevelOfRun && (!nextLeafChild() || nextLeafChild()->bidiLevel() < bidiLevelOfRun); } if (atLeftmostOffsetInBox()) { if (shouldMatchBidiLevel == IgnoreBidiLevel) return prevLeafChild() && m_inlineBox->bidiLevel() < prevLeafChild()->bidiLevel(); return prevLeafChild() && m_inlineBox->bidiLevel() < bidiLevelOfRun && prevLeafChild()->bidiLevel() >= bidiLevelOfRun; } return false; }
VisiblePosition RenderTextLineBoxes::positionForPoint(const RenderText& renderer, const LayoutPoint& point) const { if (!m_first || !renderer.textLength()) return renderer.createVisiblePosition(0, DOWNSTREAM); LayoutUnit pointLineDirection = m_first->isHorizontal() ? point.x() : point.y(); LayoutUnit pointBlockDirection = m_first->isHorizontal() ? point.y() : point.x(); bool blocksAreFlipped = renderer.style().isFlippedBlocksWritingMode(); InlineTextBox* lastBox = nullptr; for (auto box = m_first; box; box = box->nextTextBox()) { if (box->isLineBreak() && !box->prevLeafChild() && box->nextLeafChild() && !box->nextLeafChild()->isLineBreak()) box = box->nextTextBox(); auto& rootBox = box->root(); LayoutUnit top = std::min(rootBox.selectionTop(), rootBox.lineTop()); if (pointBlockDirection > top || (!blocksAreFlipped && pointBlockDirection == top)) { LayoutUnit bottom = rootBox.selectionBottom(); if (rootBox.nextRootBox()) bottom = std::min(bottom, rootBox.nextRootBox()->lineTop()); if (pointBlockDirection < bottom || (blocksAreFlipped && pointBlockDirection == bottom)) { ShouldAffinityBeDownstream shouldAffinityBeDownstream; #if PLATFORM(IOS) if (pointLineDirection != box->logicalLeft() && point.x() < box->x() + box->logicalWidth()) { int half = box->x() + box->logicalWidth() / 2; EAffinity affinity = point.x() < half ? DOWNSTREAM : VP_UPSTREAM_IF_POSSIBLE; return renderer.createVisiblePosition(box->offsetForPosition(pointLineDirection) + box->start(), affinity); } #endif if (lineDirectionPointFitsInBox(pointLineDirection, *box, shouldAffinityBeDownstream)) return createVisiblePositionAfterAdjustingOffsetForBiDi(*box, box->offsetForPosition(pointLineDirection), shouldAffinityBeDownstream); } } lastBox = box; } if (lastBox) { ShouldAffinityBeDownstream shouldAffinityBeDownstream; lineDirectionPointFitsInBox(pointLineDirection, *lastBox, shouldAffinityBeDownstream); return createVisiblePositionAfterAdjustingOffsetForBiDi(*lastBox, lastBox->offsetForPosition(pointLineDirection) + lastBox->start(), shouldAffinityBeDownstream); } return renderer.createVisiblePosition(0, DOWNSTREAM); }
unsigned char RenderedPosition::bidiLevelOnLeft() const { InlineBox* box = atLeftmostOffsetInBox() ? prevLeafChild() : m_inlineBox; return box ? box->bidiLevel() : 0; }
bool RenderedPosition::isEquivalent(const RenderedPosition& other) const { return (m_layoutObject == other.m_layoutObject && m_inlineBox == other.m_inlineBox && m_offset == other.m_offset) || (atLeftmostOffsetInBox() && other.atRightmostOffsetInBox() && prevLeafChild() == other.m_inlineBox) || (atRightmostOffsetInBox() && other.atLeftmostOffsetInBox() && nextLeafChild() == other.m_inlineBox); }
InlineBox* InlineBox::prevLeafChildIgnoringLineBreak() const { InlineBox* leaf = prevLeafChild(); return (leaf && leaf->isLineBreak()) ? nullptr : leaf; }