| Index: third_party/WebKit/Source/core/frame/LocalFrame.cpp
|
| diff --git a/third_party/WebKit/Source/core/frame/LocalFrame.cpp b/third_party/WebKit/Source/core/frame/LocalFrame.cpp
|
| index 900be2856592ddbd2a098beb70384a235e416917..ebd255b75ec08cb74b64de95990fae3ca233ed1e 100644
|
| --- a/third_party/WebKit/Source/core/frame/LocalFrame.cpp
|
| +++ b/third_party/WebKit/Source/core/frame/LocalFrame.cpp
|
| @@ -60,6 +60,8 @@
|
| #include "core/page/FocusController.h"
|
| #include "core/page/Page.h"
|
| #include "core/page/scrolling/ScrollingCoordinator.h"
|
| +#include "core/paint/ObjectPainter.h"
|
| +#include "core/paint/PaintInfo.h"
|
| #include "core/paint/PaintLayer.h"
|
| #include "core/paint/TransformRecorder.h"
|
| #include "core/svg/SVGDocumentExtensions.h"
|
| @@ -71,6 +73,7 @@
|
| #include "platform/graphics/StaticBitmapImage.h"
|
| #include "platform/graphics/paint/ClipRecorder.h"
|
| #include "platform/graphics/paint/SkPictureBuilder.h"
|
| +#include "platform/graphics/paint/TransformDisplayItem.h"
|
| #include "platform/text/TextStream.h"
|
| #include "public/platform/WebFrameScheduler.h"
|
| #include "public/platform/WebSecurityOrigin.h"
|
| @@ -85,27 +88,57 @@ using namespace HTMLNames;
|
|
|
| namespace {
|
|
|
| -struct ScopedFramePaintingState {
|
| +// Convenience class for initializing a GraphicsContext to build a DragImage from a specific
|
| +// region specified by |bounds|. After painting the using context(), the DragImage returned from
|
| +// createImage() will only contain the content in |bounds| with the appropriate device scale
|
| +// factor included.
|
| +class DragImageBuilder {
|
| STACK_ALLOCATED();
|
| public:
|
| - ScopedFramePaintingState(LocalFrame* frame, Node* node)
|
| - : frame(frame)
|
| - , node(node)
|
| + DragImageBuilder(const LocalFrame* localFrame, const IntRect& bounds, Node* draggedNode, float opacity = 1)
|
| + : m_localFrame(localFrame)
|
| + , m_draggedNode(draggedNode)
|
| + , m_bounds(bounds)
|
| + , m_opacity(opacity)
|
| {
|
| - ASSERT(!node || node->layoutObject());
|
| - if (node)
|
| - node->layoutObject()->updateDragState(true);
|
| + if (m_draggedNode && m_draggedNode->layoutObject())
|
| + m_draggedNode->layoutObject()->updateDragState(true);
|
| +
|
| + float deviceScaleFactor = m_localFrame->host()->deviceScaleFactor();
|
| + m_bounds.setWidth(m_bounds.width() * deviceScaleFactor);
|
| + m_bounds.setHeight(m_bounds.height() * deviceScaleFactor);
|
| + m_pictureBuilder = adoptPtr(new SkPictureBuilder(SkRect::MakeIWH(m_bounds.width(), m_bounds.height())));
|
| +
|
| + AffineTransform transform;
|
| + transform.scale(deviceScaleFactor, deviceScaleFactor);
|
| + transform.translate(-m_bounds.x(), -m_bounds.y());
|
| + context().paintController().createAndAppend<BeginTransformDisplayItem>(*m_localFrame, transform);
|
| }
|
|
|
| - ~ScopedFramePaintingState()
|
| + GraphicsContext& context() { return m_pictureBuilder->context(); }
|
| +
|
| + PassOwnPtr<DragImage> createImage()
|
| {
|
| - if (node && node->layoutObject())
|
| - node->layoutObject()->updateDragState(false);
|
| - frame->view()->setNodeToDraw(0);
|
| + if (m_draggedNode && m_draggedNode->layoutObject())
|
| + m_draggedNode->layoutObject()->updateDragState(false);
|
| + context().paintController().endItem<EndTransformDisplayItem>(*m_localFrame);
|
| + RefPtr<const SkPicture> recording = m_pictureBuilder->endRecording();
|
| + RefPtr<SkImage> skImage = adoptRef(SkImage::NewFromPicture(recording.get(),
|
| + SkISize::Make(m_bounds.width(), m_bounds.height()), nullptr, nullptr));
|
| + RefPtr<Image> image = StaticBitmapImage::create(skImage.release());
|
| + RespectImageOrientationEnum imageOrientation = DoNotRespectImageOrientation;
|
| + if (m_draggedNode && m_draggedNode->layoutObject())
|
| + imageOrientation = LayoutObject::shouldRespectImageOrientation(m_draggedNode->layoutObject());
|
| + return DragImage::create(image.get(), imageOrientation,
|
| + m_localFrame->host()->deviceScaleFactor(), InterpolationHigh, m_opacity);
|
| }
|
|
|
| - RawPtrWillBeMember<LocalFrame> frame;
|
| - RawPtrWillBeMember<Node> node;
|
| +private:
|
| + RawPtrWillBeMember<const LocalFrame> m_localFrame;
|
| + RawPtrWillBeMember<Node> m_draggedNode;
|
| + IntRect m_bounds;
|
| + float m_opacity;
|
| + OwnPtr<SkPictureBuilder> m_pictureBuilder;
|
| };
|
|
|
| inline float parentPageZoomFactor(LocalFrame* frame)
|
| @@ -608,63 +641,43 @@ double LocalFrame::devicePixelRatio() const
|
| return ratio;
|
| }
|
|
|
| -PassOwnPtr<DragImage> LocalFrame::paintIntoDragImage(
|
| - const DisplayItemClient& displayItemClient,
|
| - RespectImageOrientationEnum shouldRespectImageOrientation,
|
| - const GlobalPaintFlags globalPaintFlags, IntRect paintingRect, float opacity)
|
| +PassOwnPtr<DragImage> LocalFrame::paintIntoDragImage(const GlobalPaintFlags globalPaintFlags,
|
| + IntRect paintingRect, Node* draggedNode, float opacity)
|
| {
|
| ASSERT(document()->isActive());
|
| // Not flattening compositing layers will result in a broken image being painted.
|
| ASSERT(globalPaintFlags & GlobalPaintFlattenCompositingLayers);
|
|
|
| - float deviceScaleFactor = m_host->deviceScaleFactor();
|
| - paintingRect.setWidth(paintingRect.width() * deviceScaleFactor);
|
| - paintingRect.setHeight(paintingRect.height() * deviceScaleFactor);
|
| -
|
| - // The content is shifted to origin, to fit within the image bounds - which are the same
|
| - // as the picture bounds.
|
| - SkRect pictureBounds = SkRect::MakeIWH(paintingRect.width(), paintingRect.height());
|
| - SkPictureBuilder pictureBuilder(pictureBounds);
|
| - {
|
| - GraphicsContext& paintContext = pictureBuilder.context();
|
| -
|
| - AffineTransform transform;
|
| - transform.scale(deviceScaleFactor, deviceScaleFactor);
|
| - transform.translate(-paintingRect.x(), -paintingRect.y());
|
| - TransformRecorder transformRecorder(paintContext, displayItemClient, transform);
|
| -
|
| - m_view->paintContents(paintContext, globalPaintFlags, paintingRect);
|
| -
|
| - }
|
| - RefPtr<const SkPicture> recording = pictureBuilder.endRecording();
|
| - RefPtr<SkImage> skImage = adoptRef(SkImage::NewFromPicture(recording.get(),
|
| - SkISize::Make(paintingRect.width(), paintingRect.height()), nullptr, nullptr));
|
| - RefPtr<Image> image = StaticBitmapImage::create(skImage.release());
|
| -
|
| - return DragImage::create(image.get(), shouldRespectImageOrientation, deviceScaleFactor,
|
| - InterpolationHigh, opacity);
|
| + DragImageBuilder dragImageBuilder(this, paintingRect, draggedNode, opacity);
|
| + m_view->paintContents(dragImageBuilder.context(), globalPaintFlags, paintingRect);
|
| + return dragImageBuilder.createImage();
|
| }
|
|
|
| PassOwnPtr<DragImage> LocalFrame::nodeImage(Node& node)
|
| {
|
| - if (!node.layoutObject())
|
| - return nullptr;
|
| -
|
| - const ScopedFramePaintingState state(this, &node);
|
| -
|
| m_view->updateAllLifecyclePhases();
|
| -
|
| - m_view->setNodeToDraw(&node); // Enable special sub-tree drawing mode.
|
| -
|
| - // Document::updateLayout may have blown away the original LayoutObject.
|
| LayoutObject* layoutObject = node.layoutObject();
|
| if (!layoutObject)
|
| return nullptr;
|
|
|
| - IntRect rect;
|
| + // Directly paint boxes as if they are a stacking context.
|
| + if (layoutObject->isBox() && layoutObject->container()) {
|
| + IntRect boundingBox = layoutObject->absoluteBoundingBoxRectIncludingDescendants();
|
| + LayoutPoint paintOffset = boundingBox.location() - layoutObject->offsetFromContainer(layoutObject->container(), LayoutPoint());
|
| +
|
| + DragImageBuilder dragImageBuilder(this, boundingBox, &node);
|
| + {
|
| + PaintInfo paintInfo(dragImageBuilder.context(), boundingBox, PaintPhase::PaintPhaseForeground, GlobalPaintFlattenCompositingLayers, 0);
|
| + ObjectPainter(*layoutObject).paintAsPseudoStackingContext(paintInfo, LayoutPoint(paintOffset));
|
| + }
|
| + return dragImageBuilder.createImage();
|
| + }
|
|
|
| - return paintIntoDragImage(*layoutObject, LayoutObject::shouldRespectImageOrientation(layoutObject),
|
| - GlobalPaintFlattenCompositingLayers, layoutObject->paintingRootRect(rect));
|
| + // TODO(pdr): This will also paint the background if the object contains transparency. We can
|
| + // directly call layoutObject->paint(...) (see: ObjectPainter::paintAsPseudoStackingContext) but
|
| + // painters are inconsistent about which transform space they expect (see: svg, inlines, etc.)
|
| + // TODO(pdr): SVG and inlines are painted offset (crbug.com/579153, crbug.com/579158).
|
| + return paintIntoDragImage(GlobalPaintFlattenCompositingLayers, layoutObject->absoluteBoundingBoxRectIncludingDescendants(), &node);
|
| }
|
|
|
| PassOwnPtr<DragImage> LocalFrame::dragImageForSelection(float opacity)
|
| @@ -672,12 +685,10 @@ PassOwnPtr<DragImage> LocalFrame::dragImageForSelection(float opacity)
|
| if (!selection().isRange())
|
| return nullptr;
|
|
|
| - const ScopedFramePaintingState state(this, 0);
|
| m_view->updateAllLifecyclePhases();
|
|
|
| - return paintIntoDragImage(*this, DoNotRespectImageOrientation,
|
| - GlobalPaintSelectionOnly | GlobalPaintFlattenCompositingLayers,
|
| - enclosingIntRect(selection().bounds()), opacity);
|
| + return paintIntoDragImage(GlobalPaintSelectionOnly | GlobalPaintFlattenCompositingLayers,
|
| + enclosingIntRect(selection().bounds()), nullptr, opacity);
|
| }
|
|
|
| String LocalFrame::selectedText() const
|
|
|