GapRects RootInlineBox::lineSelectionGap(RenderBlock& rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock, LayoutUnit selTop, LayoutUnit selHeight, const LogicalSelectionOffsetCaches& cache, const PaintInfo* paintInfo) { RenderObject::SelectionState lineState = selectionState(); bool leftGap, rightGap; blockFlow().getSelectionGapInfo(lineState, leftGap, rightGap); GapRects result; InlineBox* firstBox = firstSelectedBox(); InlineBox* lastBox = lastSelectedBox(); if (leftGap) { result.uniteLeft(blockFlow().logicalLeftSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, &firstBox->parent()->renderer(), firstBox->logicalLeft(), selTop, selHeight, cache, paintInfo)); } if (rightGap) { result.uniteRight(blockFlow().logicalRightSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, &lastBox->parent()->renderer(), lastBox->logicalRight(), selTop, selHeight, cache, paintInfo)); } // When dealing with bidi text, a non-contiguous selection region is possible. // e.g. The logical text aaaAAAbbb (capitals denote RTL text and non-capitals LTR) is layed out // visually as 3 text runs |aaa|bbb|AAA| if we select 4 characters from the start of the text the // selection will look like (underline denotes selection): // |aaa|bbb|AAA| // ___ _ // We can see that the |bbb| run is not part of the selection while the runs around it are. if (firstBox && firstBox != lastBox) { // Now fill in any gaps on the line that occurred between two selected elements. LayoutUnit lastLogicalLeft = firstBox->logicalRight(); bool isPreviousBoxSelected = firstBox->selectionState() != RenderObject::SelectionNone; for (InlineBox* box = firstBox->nextLeafChild(); box; box = box->nextLeafChild()) { if (box->selectionState() != RenderObject::SelectionNone) { LayoutRect logicalRect(lastLogicalLeft, selTop, box->logicalLeft() - lastLogicalLeft, selHeight); logicalRect.move(renderer().isHorizontalWritingMode() ? offsetFromRootBlock : LayoutSize(offsetFromRootBlock.height(), offsetFromRootBlock.width())); LayoutRect gapRect = rootBlock.logicalRectToPhysicalRect(rootBlockPhysicalPosition, logicalRect); if (isPreviousBoxSelected && gapRect.width() > 0 && gapRect.height() > 0) { if (paintInfo && box->parent()->renderer().style().visibility() == VISIBLE) paintInfo->context->fillRect(gapRect, box->parent()->renderer().selectionBackgroundColor(), box->parent()->renderer().style().colorSpace()); // VisibleSelection may be non-contiguous, see comment above. result.uniteCenter(gapRect); } lastLogicalLeft = box->logicalRight(); } if (box == lastBox) break; isPreviousBoxSelected = box->selectionState() != RenderObject::SelectionNone; } } return result; }
GapRects RootInlineBox::fillLineSelectionGap(int selTop, int selHeight, RenderBlock* rootBlock, int blockX, int blockY, int tx, int ty, const RenderObject::PaintInfo* paintInfo) { RenderObject::SelectionState lineState = selectionState(); bool leftGap, rightGap; block()->getHorizontalSelectionGapInfo(lineState, leftGap, rightGap); GapRects result; InlineBox* firstBox = firstSelectedBox(); InlineBox* lastBox = lastSelectedBox(); if (leftGap) result.uniteLeft(block()->fillLeftSelectionGap(firstBox->parent()->renderer(), firstBox->x(), selTop, selHeight, rootBlock, blockX, blockY, tx, ty, paintInfo)); if (rightGap) result.uniteRight(block()->fillRightSelectionGap(lastBox->parent()->renderer(), lastBox->x() + lastBox->width(), selTop, selHeight, rootBlock, blockX, blockY, tx, ty, paintInfo)); // When dealing with bidi text, a non-contiguous selection region is possible. // e.g. The logical text aaaAAAbbb (capitals denote RTL text and non-capitals LTR) is layed out // visually as 3 text runs |aaa|bbb|AAA| if we select 4 characters from the start of the text the // selection will look like (underline denotes selection): // |aaa|bbb|AAA| // ___ _ // We can see that the |bbb| run is not part of the selection while the runs around it are. if (firstBox && firstBox != lastBox) { // Now fill in any gaps on the line that occurred between two selected elements. int lastX = firstBox->x() + firstBox->width(); bool isPreviousBoxSelected = firstBox->selectionState() != RenderObject::SelectionNone; for (InlineBox* box = firstBox->nextLeafChild(); box; box = box->nextLeafChild()) { if (box->selectionState() != RenderObject::SelectionNone) { if (isPreviousBoxSelected) // VisibleSelection may be non-contiguous, see comment above. result.uniteCenter(block()->fillHorizontalSelectionGap(box->parent()->renderer(), lastX + tx, selTop + ty, box->x() - lastX, selHeight, paintInfo)); lastX = box->x() + box->width(); } if (box == lastBox) break; isPreviousBoxSelected = box->selectionState() != RenderObject::SelectionNone; } } return result; }
GapRects RootInlineBox::fillLineSelectionGap(int selTop, int selHeight, RenderBlock* rootBlock, int blockX, int blockY, int tx, int ty, const RenderObject::PaintInfo* paintInfo) { RenderObject::SelectionState lineState = selectionState(); bool leftGap, rightGap; block()->getHorizontalSelectionGapInfo(lineState, leftGap, rightGap); GapRects result; InlineBox* firstBox = firstSelectedBox(); InlineBox* lastBox = lastSelectedBox(); if (leftGap) result.uniteLeft(block()->fillLeftSelectionGap(firstBox->parent()->object(), firstBox->xPos(), selTop, selHeight, rootBlock, blockX, blockY, tx, ty, paintInfo)); if (rightGap) result.uniteRight(block()->fillRightSelectionGap(lastBox->parent()->object(), lastBox->xPos() + lastBox->width(), selTop, selHeight, rootBlock, blockX, blockY, tx, ty, paintInfo)); if (firstBox && firstBox != lastBox) { // Now fill in any gaps on the line that occurred between two selected elements. int lastX = firstBox->xPos() + firstBox->width(); for (InlineBox* box = firstBox->nextLeafChild(); box; box = box->nextLeafChild()) { if (box->selectionState() != RenderObject::SelectionNone) { result.uniteCenter(block()->fillHorizontalSelectionGap(box->parent()->object(), lastX + tx, selTop + ty, box->xPos() - lastX, selHeight, paintInfo)); lastX = box->xPos() + box->width(); } if (box == lastBox) break; } } return result; }