diff options
Diffstat (limited to 'chromium/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object_test.cc')
-rw-r--r-- | chromium/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object_test.cc | 268 |
1 files changed, 268 insertions, 0 deletions
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object_test.cc b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object_test.cc new file mode 100644 index 00000000000..9b5770ef703 --- /dev/null +++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object_test.cc @@ -0,0 +1,268 @@ +// 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 "third_party/blink/renderer/core/layout/layout_geometry_map.h" +#include "third_party/blink/renderer/core/testing/core_unit_test_helper.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 = *GetDocument().getElementById("foreign"); + 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(1, 1)); + EXPECT_EQ(foreign, HitTest(149, 149)); + EXPECT_EQ(div.GetNode(), HitTest(150, 150)); + EXPECT_EQ(div.GetNode(), HitTest(349, 249)); + EXPECT_EQ(foreign, HitTest(350, 250)); + EXPECT_EQ(svg, HitTest(450, 350)); +} + +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 = *GetDocument().getElementById("foreign"); + 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(90, 90)); + EXPECT_EQ(foreign, 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(foreign, HitTest(370, 320)); + EXPECT_EQ(svg, HitTest(450, 400)); +} + +TEST_F(LayoutSVGForeignObjectTest, HitTestZoomedForeignObject) { + SetBodyInnerHTML(R"HTML( + <style>* { margin: 0; zoom: 150% }</style> + <svg id='svg' style='width: 200px; height: 200px'> + <foreignObject id='foreign' x='10' y='10' width='100' height='150'> + <div id='div' style='margin: 50px; width: 50px; height: 50px'> + </div> + </foreignObject> + </svg> + )HTML"); + + const auto& svg = *GetDocument().getElementById("svg"); + const auto& foreign = *GetDocument().getElementById("foreign"); + const auto& foreign_object = *GetLayoutObjectByElementId("foreign"); + const auto& div = *GetDocument().getElementById("div"); + + EXPECT_EQ(FloatRect(10, 10, 100, 150), 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.GetLayoutObject()->MapToVisualRectInAncestorSpace( + &GetLayoutView(), div_rect)); + EXPECT_EQ(LayoutRect(286, 286, 339, 170), div_rect); + + // mapLocalToAncestor + TransformState transform_state(TransformState::kApplyTransformDirection, + FloatPoint()); + div.GetLayoutObject()->MapLocalToAncestor(&GetLayoutView(), transform_state, + kTraverseDocumentBoundaries); + transform_state.Flatten(); + EXPECT_EQ(FloatPoint(286.875, 286.875), transform_state.LastPlanarPoint()); + + // mapAncestorToLocal + TransformState transform_state1( + TransformState::kUnapplyInverseTransformDirection, + FloatPoint(286.875, 286.875)); + div.GetLayoutObject()->MapAncestorToLocal(&GetLayoutView(), transform_state1, + kTraverseDocumentBoundaries); + transform_state1.Flatten(); + EXPECT_EQ(FloatPoint(), transform_state1.LastPlanarPoint()); + + EXPECT_EQ(svg, HitTest(20, 20)); + EXPECT_EQ(foreign, HitTest(280, 280)); + EXPECT_EQ(div, HitTest(290, 290)); +} + +TEST_F(LayoutSVGForeignObjectTest, HitTestViewBoxForeignObject) { + SetBodyInnerHTML(R"HTML( + <svg id='svg' style='width: 200px; height: 200px' viewBox='0 0 100 100'> + <foreignObject id='foreign' x='10' y='10' width='100' height='150'> + <div id='div' style='margin: 50px; width: 50px; height: 50px'> + </div> + </foreignObject> + </svg> + )HTML"); + + const auto& svg = *GetDocument().getElementById("svg"); + const auto& foreign = *GetDocument().getElementById("foreign"); + const auto& div = *GetDocument().getElementById("div"); + + // mapLocalToAncestor + TransformState transform_state(TransformState::kApplyTransformDirection, + FloatPoint()); + div.GetLayoutObject()->MapLocalToAncestor(&GetLayoutView(), transform_state, + kTraverseDocumentBoundaries); + transform_state.Flatten(); + EXPECT_EQ(FloatPoint(128, 128), transform_state.LastPlanarPoint()); + + // mapAncestorToLocal + TransformState transform_state1( + TransformState::kUnapplyInverseTransformDirection, FloatPoint(128, 128)); + div.GetLayoutObject()->MapAncestorToLocal(&GetLayoutView(), transform_state1, + kTraverseDocumentBoundaries); + transform_state1.Flatten(); + EXPECT_EQ(FloatPoint(), transform_state1.LastPlanarPoint()); + + EXPECT_EQ(svg, HitTest(20, 20)); + EXPECT_EQ(foreign, HitTest(120, 110)); + EXPECT_EQ(div, HitTest(160, 160)); +} + +TEST_F(LayoutSVGForeignObjectTest, HitTestUnderClipPath) { + SetBodyInnerHTML(R"HTML( + <style> + * { + margin: 0 + } + #target { + width: 500px; + height: 500px; + background-color: blue; + } + #target:hover { + background-color: green; + } + </style> + <svg id="svg" style="width: 500px; height: 500px"> + <clipPath id="c"> + <circle cx="250" cy="250" r="200"/> + </clipPath> + <g clip-path="url(#c)"> + <foreignObject id="foreignObject" width="100%" height="100%"> + </foreignObject> + </g> + </svg> + )HTML"); + + const auto& svg = *GetDocument().getElementById("svg"); + const auto& foreignObject = *GetDocument().getElementById("foreignObject"); + + // The fist and the third return |svg| because the circle clip-path + // clips out the foreignObject. + EXPECT_EQ(svg, GetDocument().ElementFromPoint(20, 20)); + EXPECT_EQ(foreignObject, GetDocument().ElementFromPoint(250, 250)); + EXPECT_EQ(svg, GetDocument().ElementFromPoint(400, 400)); +} + +} // namespace blink |