static RefPtr<Image> takeSnapshot(Frame& frame, IntRect rect, SnapshotOptions options, float& scaleFactor) { std::unique_ptr<ImageBuffer> buffer = snapshotFrameRect(frame, rect, options); if (!buffer) return nullptr; scaleFactor = buffer->resolutionScale(); return buffer->copyImage(CopyBackingStore, Unscaled); }
std::unique_ptr<ImageBuffer> snapshotSelection(Frame& frame, SnapshotOptions options) { if (!frame.selection().isRange()) return nullptr; options |= SnapshotOptionsPaintSelectionOnly; return snapshotFrameRect(frame, enclosingIntRect(frame.selection().bounds()), options); }
std::unique_ptr<ImageBuffer> snapshotNode(Frame& frame, Node& node) { if (!node.renderer()) return nullptr; ScopedFramePaintingState state(frame, &node); frame.view()->setBaseBackgroundColor(Color::transparent); frame.view()->setNodeToDraw(&node); LayoutRect topLevelRect; return snapshotFrameRect(frame, snappedIntRect(node.renderer()->paintingRootRect(topLevelRect))); }
std::unique_ptr<ImageBuffer> snapshotSelection(Frame& frame, SnapshotOptions options) { auto& selection = frame.selection(); if (!selection.isRange()) return nullptr; FloatRect selectionBounds = selection.selectionBounds(); // It is possible for the selection bounds to be empty; see https://bugs.webkit.org/show_bug.cgi?id=56645. if (selectionBounds.isEmpty()) return nullptr; options |= SnapshotOptionsPaintSelectionOnly; return snapshotFrameRect(frame, enclosingIntRect(selectionBounds), options); }
// FIXME (138889): Ideally the FrameSnapshotting functions would be more flexible // and we wouldn't have to implement this here. static RefPtr<Image> snapshotSelectionWithHighlight(Frame& frame) { auto& selection = frame.selection(); if (!selection.isRange()) return nullptr; FloatRect selectionBounds = selection.selectionBounds(); // It is possible for the selection bounds to be empty; see https://bugs.webkit.org/show_bug.cgi?id=56645. if (selectionBounds.isEmpty()) return nullptr; std::unique_ptr<ImageBuffer> snapshot = snapshotFrameRect(frame, enclosingIntRect(selectionBounds), 0); if (!snapshot) return nullptr; return snapshot->copyImage(CopyBackingStore, Unscaled); }
RefPtr<TextIndicator> TextIndicator::createWithSelectionInFrame(Frame& frame, TextIndicatorPresentationTransition presentationTransition, unsigned margin) { Vector<FloatRect> textRects; // On iOS, we don't need to expand the TextIndicator to cover the whole selection height. // FIXME: Ideally, on Mac, there are times when we don't need to (if we don't have a selection), // and using TextHeight would provide a more sensible appearance. #if PLATFORM(IOS) FrameSelection::TextRectangleHeight textRectHeight = FrameSelection::TextRectangleHeight::TextHeight; #else FrameSelection::TextRectangleHeight textRectHeight = FrameSelection::TextRectangleHeight::SelectionHeight; #endif frame.selection().getClippedVisibleTextRectangles(textRects, textRectHeight); // The bounding rect of all the text rects can be different than the selection // rect when the selection spans multiple lines; the indicator doesn't actually // care where the selection highlight goes, just where the text actually is. FloatRect textBoundingRectInRootViewCoordinates; FloatRect textBoundingRectInDocumentCoordinates; Vector<FloatRect> textRectsInRootViewCoordinates; for (const FloatRect& textRect : textRects) { FloatRect textRectInDocumentCoordinatesIncludingMargin = textRect; textRectInDocumentCoordinatesIncludingMargin.inflate(margin); textBoundingRectInDocumentCoordinates.unite(textRectInDocumentCoordinatesIncludingMargin); FloatRect textRectInRootViewCoordinates = frame.view()->contentsToRootView(enclosingIntRect(textRectInDocumentCoordinatesIncludingMargin)); textRectsInRootViewCoordinates.append(textRectInRootViewCoordinates); textBoundingRectInRootViewCoordinates.unite(textRectInRootViewCoordinates); } Vector<FloatRect> textRectsInBoundingRectCoordinates; for (auto rect : textRectsInRootViewCoordinates) { rect.moveBy(-textBoundingRectInRootViewCoordinates.location()); textRectsInBoundingRectCoordinates.append(rect); } // FIXME: We should have TextIndicator options instead of this being platform-specific. #if PLATFORM(IOS) SnapshotOptions snapshotOptions = SnapshotOptionsPaintSelectionAndBackgroundsOnly; #else SnapshotOptions snapshotOptions = SnapshotOptionsForceBlackText | SnapshotOptionsPaintSelectionOnly; #endif std::unique_ptr<ImageBuffer> indicatorBuffer = snapshotFrameRect(frame, enclosingIntRect(textBoundingRectInDocumentCoordinates), snapshotOptions); if (!indicatorBuffer) return nullptr; RefPtr<Image> indicatorBitmap = indicatorBuffer->copyImage(CopyBackingStore, Unscaled); if (!indicatorBitmap) return nullptr; RefPtr<Image> indicatorBitmapWithHighlight; if (presentationTransition == TextIndicatorPresentationTransition::BounceAndCrossfade) indicatorBitmapWithHighlight = snapshotSelectionWithHighlight(frame); TextIndicatorData data; // Store the selection rect in window coordinates, to be used subsequently // to determine if the indicator and selection still precisely overlap. data.selectionRectInRootViewCoordinates = frame.view()->contentsToRootView(enclosingIntRect(frame.selection().selectionBounds())); data.textBoundingRectInRootViewCoordinates = textBoundingRectInRootViewCoordinates; data.textRectsInBoundingRectCoordinates = textRectsInBoundingRectCoordinates; data.contentImageScaleFactor = indicatorBuffer->resolutionScale(); data.contentImage = indicatorBitmap; data.contentImageWithHighlight = indicatorBitmapWithHighlight; data.presentationTransition = presentationTransition; data.wantsMargin = true; return TextIndicator::create(data); }