Commit 16b3d20c authored by Chris Harrelson's avatar Chris Harrelson Committed by Commit Bot

Clip dragged images before calling CreateDragImageForFrame.

Also, pass the paint offset independently of the bounds.
The two callsites of CreateDragImageForFrame paint in different
coordinate spaces. Also, the callsite in DragController is already
clipping.

This fixes two issues: that the bounds rect did not match the
coordinate space of the clip applied in CreateDragImageForFrame,
and that the coordinate space is not necessarily the LayoutView.

Bug: 798182
Change-Id: Ie792095806613cd1e6238bbb0d1b8335350ede01
Reviewed-on: https://chromium-review.googlesource.com/848499Reviewed-by: default avatarStephen Chenney <schenney@chromium.org>
Commit-Queue: Chris Harrelson <chrishtr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#526835}
parent 40b0ca48
......@@ -103,6 +103,8 @@ class DraggedNodeImageBuilder {
layer = layer->StackingNode()->AncestorStackingContextNode()->Layer();
IntRect absolute_bounding_box =
dragged_layout_object->AbsoluteBoundingBoxRectIncludingDescendants();
absolute_bounding_box.Intersect(
layer->GetLayoutObject().GetFrameView()->VisibleContentRect());
FloatRect bounding_box =
layer->GetLayoutObject()
.AbsoluteToLocalQuad(FloatQuad(absolute_bounding_box),
......@@ -127,10 +129,12 @@ class DraggedNodeImageBuilder {
border_box_properties =
*layer->GetLayoutObject().FirstFragment().LocalBorderBoxProperties();
}
FloatPoint paint_offset = dragged_layout_object->LocalToAncestorPoint(
FloatPoint(), &layer->GetLayoutObject(), kUseTransforms);
return DataTransfer::CreateDragImageForFrame(
*local_frame_, 1.0f,
LayoutObject::ShouldRespectImageOrientation(dragged_layout_object),
bounding_box, builder, border_box_properties);
bounding_box.Size(), paint_offset, builder, border_box_properties);
}
private:
......@@ -360,14 +364,14 @@ FloatRect DataTransfer::ClipByVisualViewport(const FloatRect& rect_in_document,
}
// static
// Converts from bounds in CSS space to device space based on the given frame.
FloatRect DataTransfer::DeviceSpaceRect(const FloatRect css_rect,
// Converts from size in CSS space to device space based on the given frame.
FloatSize DataTransfer::DeviceSpaceSize(const FloatSize& css_size,
const LocalFrame& frame) {
float device_scale_factor = frame.GetPage()->DeviceScaleFactorDeprecated();
float page_scale_factor = frame.GetPage()->GetVisualViewport().Scale();
FloatRect device_rect(css_rect);
device_rect.Scale(device_scale_factor * page_scale_factor);
return device_rect;
FloatSize device_size(css_size);
device_size.Scale(device_scale_factor * page_scale_factor);
return device_size;
}
// static
......@@ -377,24 +381,25 @@ std::unique_ptr<DragImage> DataTransfer::CreateDragImageForFrame(
const LocalFrame& frame,
float opacity,
RespectImageOrientationEnum image_orientation,
const FloatRect& css_rect,
const FloatSize& css_size,
const FloatPoint& paint_offset,
PaintRecordBuilder& builder,
const PropertyTreeState& property_tree_state) {
float device_scale_factor = frame.GetPage()->DeviceScaleFactorDeprecated();
float page_scale_factor = frame.GetPage()->GetVisualViewport().Scale();
FloatRect rect_in_visual_viewport = ClipByVisualViewport(css_rect, frame);
FloatRect device_rect = DeviceSpaceRect(rect_in_visual_viewport, frame);
FloatSize device_size = DeviceSpaceSize(css_size, frame);
AffineTransform transform;
transform.Translate(-device_rect.X(), -device_rect.Y());
FloatSize paint_offset_size =
DeviceSpaceSize(FloatSize(paint_offset.X(), paint_offset.Y()), frame);
transform.Translate(-paint_offset_size.Width(), -paint_offset_size.Height());
transform.Scale(device_scale_factor * page_scale_factor);
// Rasterize upfront, since DragImage::create() is going to do it anyway
// (SkImage::asLegacyBitmap).
SkSurfaceProps surface_props(0, kUnknown_SkPixelGeometry);
sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(
device_rect.Width(), device_rect.Height(), &surface_props);
device_size.Width(), device_size.Height(), &surface_props);
if (!surface)
return nullptr;
......
......@@ -136,13 +136,19 @@ class CORE_EXPORT DataTransfer final : public ScriptWrappable,
static FloatRect ClipByVisualViewport(const FloatRect& rect_in_document,
const LocalFrame&);
// Returns the rect with device scale factor and page scale factor applied.
static FloatRect DeviceSpaceRect(const FloatRect css_rect, const LocalFrame&);
// Returns the size with device scale factor and page scale factor applied.
static FloatSize DeviceSpaceSize(const FloatSize& css_size,
const LocalFrame&);
// |css_size| is the size of the image in CSS pixels.
// |paint_offset| is the offset from the origin of the dragged
// object of the PaintRecordBuilder.
static std::unique_ptr<DragImage> CreateDragImageForFrame(
const LocalFrame&,
float,
RespectImageOrientationEnum,
const FloatRect&,
const FloatSize& css_size,
const FloatPoint& paint_offset,
PaintRecordBuilder&,
const PropertyTreeState&);
static std::unique_ptr<DragImage> NodeImage(const LocalFrame&, Node&);
......
......@@ -235,4 +235,32 @@ TEST_P(DataTransferTest, NodeImageWithPageScaleFactor) {
EXPECT_EQ(expected_bitmap.getColor(x, y), bitmap.getColor(x, y));
}
TEST_P(DataTransferTest, NodeImageWithScrolling) {
SetBodyInnerHTML(R"HTML(
<style>
#inner {
position: absolute;
top: 800px;
left: 0;
height: 100px;
width: 200px;
background: lightblue;
isolation: isolate;
}
</style>
<div id="inner" draggable="true" ondragstart="drag(event)"></div>
)HTML");
const int scroll_amount = 800;
LocalFrameView* frame_view = GetDocument().View();
frame_view->LayoutViewportScrollableArea()->SetScrollOffset(
ScrollOffset(0, scroll_amount), kProgrammaticScroll);
Element& inner = *GetDocument().getElementById("inner");
const auto image = DataTransfer::NodeImage(GetFrame(), inner);
const int inner_width = 200;
const int inner_height = 100;
EXPECT_EQ(IntSize(inner_width, inner_height), image->Size());
}
} // namespace blink
......@@ -1146,8 +1146,8 @@ std::unique_ptr<DragImage> DragController::DragImageForSelection(
frame.View()->PaintContents(builder.Context(), paint_flags,
EnclosingIntRect(painting_rect));
return DataTransfer::CreateDragImageForFrame(
frame, opacity, kDoNotRespectImageOrientation, painting_rect, builder,
PropertyTreeState::Root());
frame, opacity, kDoNotRespectImageOrientation, painting_rect.Size(),
painting_rect.Location(), builder, PropertyTreeState::Root());
}
bool DragController::StartDrag(LocalFrame* src,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment