GapRects RenderBlockFlow::inlineSelectionGaps(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock, LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const PaintInfo* paintInfo) { GapRects result; bool containsStart = selectionState() == SelectionStart || selectionState() == SelectionBoth; if (!firstLineBox()) { if (containsStart) { // Go ahead and update our lastLogicalTop to be the bottom of the block. <hr>s or empty blocks with height can trip this // case. lastLogicalTop = rootBlock->blockDirectionOffset(offsetFromRootBlock) + logicalHeight(); lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, logicalHeight()); lastLogicalRight = logicalRightSelectionOffset(rootBlock, logicalHeight()); } return result; } RootInlineBox* lastSelectedLine = 0; RootInlineBox* curr; for (curr = firstRootBox(); curr && !curr->hasSelectedChildren(); curr = curr->nextRootBox()) { } // Now paint the gaps for the lines. for (; curr && curr->hasSelectedChildren(); curr = curr->nextRootBox()) { LayoutUnit selTop = curr->selectionTopAdjustedForPrecedingBlock(); LayoutUnit selHeight = curr->selectionHeightAdjustedForPrecedingBlock(); if (!containsStart && !lastSelectedLine && selectionState() != SelectionStart && selectionState() != SelectionBoth) { result.uniteCenter(blockSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight, selTop, paintInfo)); } LayoutRect logicalRect(curr->logicalLeft(), selTop, curr->logicalWidth(), selTop + selHeight); logicalRect.move(offsetFromRootBlock); LayoutRect physicalRect = rootBlock->logicalRectToPhysicalRect(rootBlockPhysicalPosition, logicalRect); if (!paintInfo || (physicalRect.y() < paintInfo->rect.maxY() && physicalRect.maxY() > paintInfo->rect.y())) result.unite(curr->lineSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, selTop, selHeight, paintInfo)); lastSelectedLine = curr; } if (containsStart && !lastSelectedLine) { // VisibleSelection must start just after our last line. lastSelectedLine = lastRootBox(); } if (lastSelectedLine && selectionState() != SelectionEnd && selectionState() != SelectionBoth) { // Go ahead and update our lastY to be the bottom of the last selected line. lastLogicalTop = rootBlock->blockDirectionOffset(offsetFromRootBlock) + lastSelectedLine->selectionBottom(); lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, lastSelectedLine->selectionBottom()); lastLogicalRight = logicalRightSelectionOffset(rootBlock, lastSelectedLine->selectionBottom()); } return result; }
VisiblePosition RenderReplaced::positionForPoint(const IntPoint& point) { InlineBox* box = inlineBoxWrapper(); if (!box) return createVisiblePosition(0, DOWNSTREAM); // FIXME: This code is buggy if the replaced element is relative positioned. RootInlineBox* root = box->root(); int top = root->selectionTop(); int bottom = root->selectionBottom(); int blockDirectionPosition = box->isHorizontal() ? point.y() + y() : point.x() + x(); int lineDirectionPosition = box->isHorizontal() ? point.x() + x() : point.y() + y(); if (blockDirectionPosition < top) return createVisiblePosition(caretMinOffset(), DOWNSTREAM); // coordinates are above if (blockDirectionPosition >= bottom) return createVisiblePosition(caretMaxOffset(), DOWNSTREAM); // coordinates are below if (node()) { if (lineDirectionPosition <= box->logicalLeft() + (box->logicalWidth() / 2)) return createVisiblePosition(0, DOWNSTREAM); return createVisiblePosition(1, DOWNSTREAM); } return RenderBox::positionForPoint(point); }
PositionWithAffinity RenderReplaced::positionForPoint(const LayoutPoint& point) { // FIXME: This code is buggy if the replaced element is relative positioned. InlineBox* box = inlineBoxWrapper(); RootInlineBox* rootBox = box ? &box->root() : 0; LayoutUnit top = rootBox ? rootBox->selectionTop() : logicalTop(); LayoutUnit bottom = rootBox ? rootBox->selectionBottom() : logicalBottom(); LayoutUnit blockDirectionPosition = isHorizontalWritingMode() ? point.y() + y() : point.x() + x(); LayoutUnit lineDirectionPosition = isHorizontalWritingMode() ? point.x() + x() : point.y() + y(); if (blockDirectionPosition < top) return createPositionWithAffinity(caretMinOffset(), DOWNSTREAM); // coordinates are above if (blockDirectionPosition >= bottom) return createPositionWithAffinity(caretMaxOffset(), DOWNSTREAM); // coordinates are below if (node()) { if (lineDirectionPosition <= logicalLeft() + (logicalWidth() / 2)) return createPositionWithAffinity(0, DOWNSTREAM); return createPositionWithAffinity(1, DOWNSTREAM); } return RenderBox::positionForPoint(point); }
IntRect RenderReplaced::localSelectionRect(bool checkWhetherSelected) const { if (checkWhetherSelected && !isSelected()) return IntRect(); if (!m_inlineBoxWrapper) // We're a block-level replaced element. Just return our own dimensions. return IntRect(0, 0, width(), height()); RootInlineBox* root = m_inlineBoxWrapper->root(); int newLogicalTop = root->block()->style()->isFlippedBlocksWritingMode() ? m_inlineBoxWrapper->logicalBottom() - root->selectionBottom() : root->selectionTop() - m_inlineBoxWrapper->logicalTop(); if (root->block()->style()->isHorizontalWritingMode()) return IntRect(0, newLogicalTop, width(), root->selectionHeight()); return IntRect(newLogicalTop, 0, root->selectionHeight(), height()); }