// 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()))); }
LayoutUnit RenderFlowThread::offsetFromLogicalTopOfFirstRegion(const RenderBlock* currentBlock) const { // First check if we cached the offset for the block if it's an ancestor containing block of the box // being currently laid out. LayoutUnit offset; if (cachedOffsetFromLogicalTopOfFirstRegion(currentBlock, offset)) return offset; // If it's the current box being laid out, use the layout state. const RenderBox* currentBoxDescendant = currentStatePusherRenderBox(); if (currentBlock == currentBoxDescendant) { LayoutState* layoutState = view()->layoutState(); ASSERT(layoutState->renderer() == currentBlock); ASSERT(layoutState && layoutState->isPaginated()); LayoutSize offsetDelta = layoutState->layoutOffset() - layoutState->pageOffset(); return currentBoxDescendant->isHorizontalWritingMode() ? offsetDelta.height() : offsetDelta.width(); } // As a last resort, take the slow path. LayoutRect blockRect(0, 0, currentBlock->width(), currentBlock->height()); while (currentBlock && !currentBlock->isRenderFlowThread()) { RenderBlock* containerBlock = currentBlock->containingBlock(); ASSERT(containerBlock); if (!containerBlock) return 0; LayoutPoint currentBlockLocation = currentBlock->location(); if (containerBlock->style()->writingMode() != currentBlock->style()->writingMode()) { // We have to put the block rect in container coordinates // and we have to take into account both the container and current block flipping modes if (containerBlock->style()->isFlippedBlocksWritingMode()) { if (containerBlock->isHorizontalWritingMode()) blockRect.setY(currentBlock->height() - blockRect.maxY()); else blockRect.setX(currentBlock->width() - blockRect.maxX()); } currentBlock->flipForWritingMode(blockRect); } blockRect.moveBy(currentBlockLocation); currentBlock = containerBlock; } return currentBlock->isHorizontalWritingMode() ? blockRect.y() : blockRect.x(); }