void RenderLineBreak::collectSelectionRects(Vector<SelectionRect>& rects, unsigned, unsigned) { ensureLineBoxes(*this); InlineElementBox* box = m_inlineBoxWrapper; if (!box) return; const RootInlineBox& rootBox = box->root(); LayoutRect rect = rootBox.computeCaretRect(box->logicalLeft(), 0, nullptr); if (rootBox.isFirstAfterPageBreak()) { if (box->isHorizontal()) rect.shiftYEdgeTo(rootBox.lineTopWithLeading()); else rect.shiftXEdgeTo(rootBox.lineTopWithLeading()); } RenderBlock* containingBlock = this->containingBlock(); // Map rect, extended left to leftOffset, and right to rightOffset, through transforms to get minX and maxX. LogicalSelectionOffsetCaches cache(*containingBlock); LayoutUnit leftOffset = containingBlock->logicalLeftSelectionOffset(*containingBlock, box->logicalTop(), cache); LayoutUnit rightOffset = containingBlock->logicalRightSelectionOffset(*containingBlock, box->logicalTop(), cache); LayoutRect extentsRect = rect; if (box->isHorizontal()) { extentsRect.setX(leftOffset); extentsRect.setWidth(rightOffset - leftOffset); } else { extentsRect.setY(leftOffset); extentsRect.setHeight(rightOffset - leftOffset); } extentsRect = localToAbsoluteQuad(FloatRect(extentsRect)).enclosingBoundingBox(); if (!box->isHorizontal()) extentsRect = extentsRect.transposedRect(); bool isFirstOnLine = !box->previousOnLineExists(); bool isLastOnLine = !box->nextOnLineExists(); if (containingBlock->isRubyBase() || containingBlock->isRubyText()) isLastOnLine = !containingBlock->containingBlock()->inlineBoxWrapper()->nextOnLineExists(); bool isFixed = false; IntRect absRect = localToAbsoluteQuad(FloatRect(rect), UseTransforms, &isFixed).enclosingBoundingBox(); bool boxIsHorizontal = !box->isSVGInlineTextBox() ? box->isHorizontal() : !style().svgStyle().isVerticalWritingMode(); // If the containing block is an inline element, we want to check the inlineBoxWrapper orientation // to determine the orientation of the block. In this case we also use the inlineBoxWrapper to // determine if the element is the last on the line. if (containingBlock->inlineBoxWrapper()) { if (containingBlock->inlineBoxWrapper()->isHorizontal() != boxIsHorizontal) { boxIsHorizontal = containingBlock->inlineBoxWrapper()->isHorizontal(); isLastOnLine = !containingBlock->inlineBoxWrapper()->nextOnLineExists(); } } rects.append(SelectionRect(absRect, box->direction(), extentsRect.x(), extentsRect.maxX(), extentsRect.maxY(), 0, box->isLineBreak(), isFirstOnLine, isLastOnLine, false, false, boxIsHorizontal, isFixed, containingBlock->isRubyText(), view().pageNumberForBlockProgressionOffset(absRect.x()))); }
// FIXME: This doesn't behave correctly for floating or positioned images, but WebCore doesn't handle those well // during selection creation yet anyway. // FIXME: We can't tell whether or not we contain the start or end of the selected Range using only the offsets // of the start and end, we need to know the whole Position. void RenderImage::collectSelectionRects(Vector<SelectionRect>& rects, unsigned, unsigned) { RenderBlock* containingBlock = this->containingBlock(); IntRect imageRect; // FIXME: It doesn't make sense to package line bounds into SelectionRects. We should find // the right and left extent of the selection once for the entire selected Range, perhaps // using the Range's common ancestor. IntRect lineExtentRect; bool isFirstOnLine = false; bool isLastOnLine = false; InlineBox* inlineBox = inlineBoxWrapper(); if (!inlineBox) { // This is a block image. imageRect = IntRect(0, 0, width(), height()); isFirstOnLine = true; isLastOnLine = true; lineExtentRect = imageRect; if (containingBlock->isHorizontalWritingMode()) { lineExtentRect.setX(containingBlock->x()); lineExtentRect.setWidth(containingBlock->width()); } else { lineExtentRect.setY(containingBlock->y()); lineExtentRect.setHeight(containingBlock->height()); } } else { LayoutUnit selectionTop = !containingBlock->style().isFlippedBlocksWritingMode() ? inlineBox->root().selectionTop() - logicalTop() : logicalBottom() - inlineBox->root().selectionBottom(); imageRect = IntRect(0, selectionTop, logicalWidth(), inlineBox->root().selectionHeight()); isFirstOnLine = !inlineBox->previousOnLineExists(); isLastOnLine = !inlineBox->nextOnLineExists(); LogicalSelectionOffsetCaches cache(*containingBlock); LayoutUnit leftOffset = containingBlock->logicalLeftSelectionOffset(*containingBlock, inlineBox->logicalTop(), cache); LayoutUnit rightOffset = containingBlock->logicalRightSelectionOffset(*containingBlock, inlineBox->logicalTop(), cache); lineExtentRect = IntRect(leftOffset - logicalLeft(), imageRect.y(), rightOffset - leftOffset, imageRect.height()); if (!inlineBox->isHorizontal()) { imageRect = imageRect.transposedRect(); lineExtentRect = lineExtentRect.transposedRect(); } } bool isFixed = false; IntRect absoluteBounds = localToAbsoluteQuad(FloatRect(imageRect), UseTransforms, &isFixed).enclosingBoundingBox(); IntRect lineExtentBounds = localToAbsoluteQuad(FloatRect(lineExtentRect)).enclosingBoundingBox(); if (!containingBlock->isHorizontalWritingMode()) lineExtentBounds = lineExtentBounds.transposedRect(); // FIXME: We should consider either making SelectionRect a struct or better organize its optional fields into // an auxiliary struct to simplify its initialization. rects.append(SelectionRect(absoluteBounds, containingBlock->style().direction(), lineExtentBounds.x(), lineExtentBounds.maxX(), lineExtentBounds.maxY(), 0, false /* line break */, isFirstOnLine, isLastOnLine, false /* contains start */, false /* contains end */, containingBlock->style().isHorizontalWritingMode(), isFixed, false /* ruby text */, view().pageNumberForBlockProgressionOffset(absoluteBounds.x()))); }