blob: 1a6081a75b21fbf0db2d16d9cee6807526e5628e [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "core/layout/LayoutGeometryMap.h"
#include "core/layout/LayoutTestHelper.h"
namespace blink {
class LayoutSVGForeignObjectTest : public RenderingTest {
public:
LayoutSVGForeignObjectTest()
: RenderingTest(SingleChildLocalFrameClient::Create()) {}
const Node* HitTest(int x, int y) {
HitTestResult result(
HitTestRequest(HitTestRequest::kReadOnly | HitTestRequest::kActive |
HitTestRequest::kAllowChildFrameContent),
IntPoint(x, y));
GetLayoutView().HitTest(result);
return result.InnerNode();
}
};
TEST_F(LayoutSVGForeignObjectTest, DivInForeignObject) {
SetBodyInnerHTML(R"HTML(
<style>body { margin: 0 }</style>
<svg id='svg' style='width: 500px; height: 400px'>
<foreignObject id='foreign' x='100' y='100' width='300' height='200'>
<div id='div' style='margin: 50px; width: 200px; height: 100px'>
</div>
</foreignObject>
</svg>
)HTML");
const auto& svg = *GetDocument().getElementById("svg");
const auto& foreign_object = *GetLayoutObjectByElementId("foreign");
const auto& div = *GetLayoutObjectByElementId("div");
EXPECT_EQ(FloatRect(100, 100, 300, 200), foreign_object.ObjectBoundingBox());
EXPECT_EQ(AffineTransform(), foreign_object.LocalSVGTransform());
EXPECT_EQ(AffineTransform(), foreign_object.LocalToSVGParentTransform());
// mapToVisualRectInAncestorSpace
LayoutRect div_rect(0, 0, 100, 50);
EXPECT_TRUE(div.MapToVisualRectInAncestorSpace(&GetLayoutView(), div_rect));
EXPECT_EQ(LayoutRect(150, 150, 100, 50), div_rect);
// mapLocalToAncestor
TransformState transform_state(TransformState::kApplyTransformDirection,
FloatPoint());
div.MapLocalToAncestor(&GetLayoutView(), transform_state,
kTraverseDocumentBoundaries);
transform_state.Flatten();
EXPECT_EQ(FloatPoint(150, 150), transform_state.LastPlanarPoint());
// mapAncestorToLocal
TransformState transform_state1(
TransformState::kUnapplyInverseTransformDirection, FloatPoint());
div.MapAncestorToLocal(&GetLayoutView(), transform_state1,
kTraverseDocumentBoundaries);
transform_state1.Flatten();
EXPECT_EQ(FloatPoint(-150, -150), transform_state1.LastPlanarPoint());
// pushMappingToContainer
LayoutGeometryMap rgm(kTraverseDocumentBoundaries);
rgm.PushMappingsToAncestor(&div, nullptr);
EXPECT_EQ(FloatQuad(FloatRect(150, 150, 1, 2)),
rgm.MapToAncestor(FloatRect(0, 0, 1, 2), nullptr));
// Hit testing
EXPECT_EQ(svg, HitTest(149, 149));
EXPECT_EQ(div.GetNode(), HitTest(150, 150));
EXPECT_EQ(div.GetNode(), HitTest(349, 249));
EXPECT_EQ(svg, HitTest(350, 250));
}
TEST_F(LayoutSVGForeignObjectTest, IframeInForeignObject) {
SetBodyInnerHTML(R"HTML(
<style>body { margin: 0 }</style>
<svg id='svg' style='width: 500px; height: 450px'>
<foreignObject id='foreign' x='100' y='100' width='300' height='250'>
<iframe style='border: none; margin: 30px;
width: 240px; height: 190px'></iframe>
</foreignObject>
</svg>
)HTML");
SetChildFrameHTML(R"HTML(
<style>
body { margin: 0 }
* { background: white; }
</style>
<div id='div' style='margin: 70px; width: 100px; height: 50px'></div>
)HTML");
GetDocument().View()->UpdateAllLifecyclePhases();
const auto& svg = *GetDocument().getElementById("svg");
const auto& foreign_object = *GetLayoutObjectByElementId("foreign");
const auto& div = *ChildDocument().getElementById("div")->GetLayoutObject();
EXPECT_EQ(FloatRect(100, 100, 300, 250), foreign_object.ObjectBoundingBox());
EXPECT_EQ(AffineTransform(), foreign_object.LocalSVGTransform());
EXPECT_EQ(AffineTransform(), foreign_object.LocalToSVGParentTransform());
// mapToVisualRectInAncestorSpace
LayoutRect div_rect(0, 0, 100, 50);
EXPECT_TRUE(div.MapToVisualRectInAncestorSpace(&GetLayoutView(), div_rect));
EXPECT_EQ(LayoutRect(200, 200, 100, 50), div_rect);
// mapLocalToAncestor
TransformState transform_state(TransformState::kApplyTransformDirection,
FloatPoint());
div.MapLocalToAncestor(&GetLayoutView(), transform_state,
kTraverseDocumentBoundaries);
transform_state.Flatten();
EXPECT_EQ(FloatPoint(200, 200), transform_state.LastPlanarPoint());
// mapAncestorToLocal
TransformState transform_state1(
TransformState::kUnapplyInverseTransformDirection, FloatPoint());
div.MapAncestorToLocal(&GetLayoutView(), transform_state1,
kTraverseDocumentBoundaries);
transform_state1.Flatten();
EXPECT_EQ(FloatPoint(-200, -200), transform_state1.LastPlanarPoint());
// pushMappingToContainer
LayoutGeometryMap rgm(kTraverseDocumentBoundaries);
rgm.PushMappingsToAncestor(&div, nullptr);
EXPECT_EQ(FloatQuad(FloatRect(200, 200, 1, 2)),
rgm.MapToAncestor(FloatRect(0, 0, 1, 2), nullptr));
// Hit testing
EXPECT_EQ(svg, HitTest(129, 129));
EXPECT_EQ(ChildDocument().documentElement(), HitTest(130, 130));
EXPECT_EQ(ChildDocument().documentElement(), HitTest(199, 199));
EXPECT_EQ(div.GetNode(), HitTest(200, 200));
EXPECT_EQ(div.GetNode(), HitTest(299, 249));
EXPECT_EQ(ChildDocument().documentElement(), HitTest(300, 250));
EXPECT_EQ(ChildDocument().documentElement(), HitTest(369, 319));
EXPECT_EQ(svg, HitTest(370, 320));
}
} // namespace blink