| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "core/layout/LayoutObject.h" | 5 #include "core/layout/LayoutObject.h" |
| 6 | 6 |
| 7 #include "core/layout/LayoutTestHelper.h" | 7 #include "core/layout/LayoutTestHelper.h" |
| 8 #include "core/layout/LayoutView.h" | 8 #include "core/layout/LayoutView.h" |
| 9 #include "testing/gtest/include/gtest/gtest.h" | 9 #include "testing/gtest/include/gtest/gtest.h" |
| 10 | 10 |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 102 LayoutObject* layoutObject = bodyLayoutObject->slowFirstChild()->slowFirstCh
ild(); | 102 LayoutObject* layoutObject = bodyLayoutObject->slowFirstChild()->slowFirstCh
ild(); |
| 103 | 103 |
| 104 // Sanity check: Make sure we don't generate anonymous objects. | 104 // Sanity check: Make sure we don't generate anonymous objects. |
| 105 EXPECT_EQ(nullptr, bodyLayoutObject->slowFirstChild()->nextSibling()); | 105 EXPECT_EQ(nullptr, bodyLayoutObject->slowFirstChild()->nextSibling()); |
| 106 EXPECT_EQ(nullptr, layoutObject->slowFirstChild()); | 106 EXPECT_EQ(nullptr, layoutObject->slowFirstChild()); |
| 107 EXPECT_EQ(nullptr, layoutObject->nextSibling()); | 107 EXPECT_EQ(nullptr, layoutObject->nextSibling()); |
| 108 | 108 |
| 109 EXPECT_EQ(layoutObject->containingBlock(), bodyLayoutObject); | 109 EXPECT_EQ(layoutObject->containingBlock(), bodyLayoutObject); |
| 110 } | 110 } |
| 111 | 111 |
| 112 TEST_F(LayoutObjectTest, LayoutTextMapToVisualRectInAncestorSpace) | |
| 113 { | |
| 114 setBodyInnerHTML( | |
| 115 "<style>body { margin: 0; }</style>" | |
| 116 "<div id='container' style='overflow: scroll; width: 50px; height: 50px'
>" | |
| 117 " <span><img style='width: 20px; height: 100px'></span>" | |
| 118 " text text text text text text text" | |
| 119 "</div>"); | |
| 120 | |
| 121 LayoutBlock* container = toLayoutBlock(getLayoutObjectByElementId("container
")); | |
| 122 LayoutText* text = toLayoutText(container->lastChild()); | |
| 123 | |
| 124 container->setScrollTop(LayoutUnit(50)); | |
| 125 LayoutRect rect(0, 60, 20, 80); | |
| 126 EXPECT_TRUE(text->mapToVisualRectInAncestorSpace(container, rect)); | |
| 127 EXPECT_EQ(rect, LayoutRect(0, 10, 20, 80)); | |
| 128 | |
| 129 rect = LayoutRect(0, 60, 80, 0); | |
| 130 EXPECT_TRUE(text->mapToVisualRectInAncestorSpace(container, rect, EdgeInclus
ive)); | |
| 131 EXPECT_EQ(rect, LayoutRect(0, 10, 80, 0)); | |
| 132 } | |
| 133 | |
| 134 TEST_F(LayoutObjectTest, LayoutInlineMapToVisualRectInAncestorSpace) | |
| 135 { | |
| 136 document().setBaseURLOverride(KURL(ParsedURLString, "http://test.com")); | |
| 137 setBodyInnerHTML( | |
| 138 "<style>body { margin: 0; }</style>" | |
| 139 "<div id='container' style='overflow: scroll; width: 50px; height: 50px'
>" | |
| 140 " <span><img style='width: 20px; height: 100px'></span>" | |
| 141 " <span id=leaf></span></div>"); | |
| 142 | |
| 143 LayoutBlock* container = toLayoutBlock(getLayoutObjectByElementId("container
")); | |
| 144 LayoutObject* leaf = container->lastChild(); | |
| 145 | |
| 146 container->setScrollTop(LayoutUnit(50)); | |
| 147 LayoutRect rect(0, 60, 20, 80); | |
| 148 EXPECT_TRUE(leaf->mapToVisualRectInAncestorSpace(container, rect)); | |
| 149 EXPECT_EQ(rect, LayoutRect(0, 10, 20, 80)); | |
| 150 | |
| 151 rect = LayoutRect(0, 60, 80, 0); | |
| 152 EXPECT_TRUE(leaf->mapToVisualRectInAncestorSpace(container, rect, EdgeInclus
ive)); | |
| 153 EXPECT_EQ(rect, LayoutRect(0, 10, 80, 0)); | |
| 154 } | |
| 155 | |
| 156 TEST_F(LayoutObjectTest, LayoutViewMapToVisualRectInAncestorSpace) | |
| 157 { | |
| 158 document().setBaseURLOverride(KURL(ParsedURLString, "http://test.com")); | |
| 159 setBodyInnerHTML( | |
| 160 "<style>body { margin: 0; }</style>" | |
| 161 "<div id=frameContainer>" | |
| 162 " <iframe id=frame src='http://test.com' width='50' height='50' frameBo
rder='0'></iframe>" | |
| 163 "</div>"); | |
| 164 | |
| 165 Document& frameDocument = setupChildIframe("frame", "<style>body { margin: 0
; }</style><span><img style='width: 20px; height: 100px'></span>text text text")
; | |
| 166 frameDocument.updateLayout(); | |
| 167 | |
| 168 LayoutBlock* frameContainer = toLayoutBlock(getLayoutObjectByElementId("fram
eContainer")); | |
| 169 LayoutBlock* frameBody = toLayoutBlock(frameDocument.body()->layoutObject())
; | |
| 170 LayoutText* frameText = toLayoutText(frameBody->lastChild()); | |
| 171 | |
| 172 // This case involves clipping: frame height is 50, y-coordinate of result r
ect is 13, | |
| 173 // so height should be clipped to (50 - 13) == 37. | |
| 174 frameDocument.view()->setScrollPosition(DoublePoint(0, 47), ProgrammaticScro
ll); | |
| 175 LayoutRect rect(4, 60, 20, 80); | |
| 176 EXPECT_TRUE(frameText->mapToVisualRectInAncestorSpace(frameContainer, rect))
; | |
| 177 EXPECT_EQ(rect, LayoutRect(4, 13, 20, 37)); | |
| 178 | |
| 179 rect = LayoutRect(4, 60, 0, 80); | |
| 180 EXPECT_TRUE(frameText->mapToVisualRectInAncestorSpace(frameContainer, rect,
EdgeInclusive)); | |
| 181 EXPECT_EQ(rect, LayoutRect(4, 13, 0, 37)); | |
| 182 } | |
| 183 | |
| 184 TEST_F(LayoutObjectTest, LayoutViewMapToVisualRectInAncestorSpaceSubpixelRoundin
g) | |
| 185 { | |
| 186 document().setBaseURLOverride(KURL(ParsedURLString, "http://test.com")); | |
| 187 setBodyInnerHTML( | |
| 188 "<style>body { margin: 0; }</style>" | |
| 189 "<div id=frameContainer style='position: relative; left: 0.5px'>" | |
| 190 " <iframe id=frame style='position: relative; left: 0.5px' src='http://
test.com' width='200' height='200' frameBorder='0'></iframe>" | |
| 191 "</div>"); | |
| 192 | |
| 193 Document& frameDocument = setupChildIframe( | |
| 194 "frame", "<style>body { margin: 0; }</style><div id='target' style='posi
tion: relative; width: 100px; height: 100px; left: 0.5px'>"); | |
| 195 frameDocument.updateLayout(); | |
| 196 | |
| 197 LayoutBlock* frameContainer = toLayoutBlock(getLayoutObjectByElementId("fram
eContainer")); | |
| 198 LayoutObject* target = frameDocument.getElementById("target")->layoutObject(
); | |
| 199 LayoutRect rect(0, 0, 100, 100); | |
| 200 EXPECT_TRUE(target->mapToVisualRectInAncestorSpace(frameContainer, rect)); | |
| 201 // When passing from the iframe to the parent frame, the rect of (0.5, 0, 10
0, 100) is expanded to (0, 0, 100, 100), and then offset by | |
| 202 // the 0.5 offset of frameContainer. | |
| 203 EXPECT_EQ(LayoutRect(LayoutPoint(DoublePoint(0.5, 0)), LayoutSize(101, 100))
, rect); | |
| 204 } | |
| 205 | |
| 206 TEST_F(LayoutObjectTest, OverflowRectMappingWithSelfFlippedWritingMode) | |
| 207 { | |
| 208 setBodyInnerHTML( | |
| 209 "<div id='target' style='writing-mode: vertical-rl; box-shadow: 40px 20p
x black;" | |
| 210 " width: 100px; height: 50px; position: absolute; top: 111px; left: 2
22px'>" | |
| 211 "</div>"); | |
| 212 | |
| 213 LayoutBlock* target = toLayoutBlock(getLayoutObjectByElementId("target")); | |
| 214 LayoutRect overflowRect = target->localOverflowRectForPaintInvalidation(); | |
| 215 // -40 = -box_shadow_offset_x(40) (with target's top-right corner as the ori
gin) | |
| 216 // 140 = width(100) + box_shadow_offset_x(40) | |
| 217 // 70 = height(50) + box_shadow_offset_y(20) | |
| 218 EXPECT_EQ(LayoutRect(-40, 0, 140, 70), overflowRect); | |
| 219 | |
| 220 LayoutRect rect = overflowRect; | |
| 221 EXPECT_TRUE(target->mapToVisualRectInAncestorSpace(target, rect)); | |
| 222 // This rect is in physical coordinates of target. | |
| 223 EXPECT_EQ(LayoutRect(0, 0, 140, 70), rect); | |
| 224 | |
| 225 rect = overflowRect; | |
| 226 EXPECT_TRUE(target->mapToVisualRectInAncestorSpace(&layoutView(), rect)); | |
| 227 EXPECT_EQ(LayoutRect(222, 111, 140, 70), rect); | |
| 228 } | |
| 229 | |
| 230 TEST_F(LayoutObjectTest, OverflowRectMappingWithContainerFlippedWritingMode) | |
| 231 { | |
| 232 setBodyInnerHTML( | |
| 233 "<div id='container' style='writing-mode: vertical-rl; position: absolut
e; top: 111px; left: 222px'>" | |
| 234 " <div id='target' style='box-shadow: 40px 20px black; width: 100px;
height: 90px'></div>" | |
| 235 " <div style='width: 100px; height: 100px'></div>" | |
| 236 "</div>"); | |
| 237 | |
| 238 LayoutBlock* target = toLayoutBlock(getLayoutObjectByElementId("target")); | |
| 239 LayoutRect targetOverflowRect = target->localOverflowRectForPaintInvalidatio
n(); | |
| 240 // -40 = -box_shadow_offset_x(40) (with target's top-right corner as the ori
gin) | |
| 241 // 140 = width(100) + box_shadow_offset_x(40) | |
| 242 // 110 = height(90) + box_shadow_offset_y(20) | |
| 243 EXPECT_EQ(LayoutRect(-40, 0, 140, 110), targetOverflowRect); | |
| 244 | |
| 245 LayoutRect rect = targetOverflowRect; | |
| 246 EXPECT_TRUE(target->mapToVisualRectInAncestorSpace(target, rect)); | |
| 247 // This rect is in physical coordinates of target. | |
| 248 EXPECT_EQ(LayoutRect(0, 0, 140, 110), rect); | |
| 249 | |
| 250 LayoutBlock* container = toLayoutBlock(getLayoutObjectByElementId("container
")); | |
| 251 rect = targetOverflowRect; | |
| 252 EXPECT_TRUE(target->mapToVisualRectInAncestorSpace(container, rect)); | |
| 253 // 100 is the physical x location of target in container. | |
| 254 EXPECT_EQ(LayoutRect(100, 0, 140, 110), rect); | |
| 255 rect = targetOverflowRect; | |
| 256 EXPECT_TRUE(target->mapToVisualRectInAncestorSpace(&layoutView(), rect)); | |
| 257 EXPECT_EQ(LayoutRect(322, 111, 140, 110), rect); | |
| 258 | |
| 259 LayoutRect containerOverflowRect = container->localOverflowRectForPaintInval
idation(); | |
| 260 EXPECT_EQ(LayoutRect(-40, 0, 240, 110), containerOverflowRect); | |
| 261 rect = containerOverflowRect; | |
| 262 EXPECT_TRUE(container->mapToVisualRectInAncestorSpace(container, rect)); | |
| 263 EXPECT_EQ(LayoutRect(0, 0, 240, 110), rect); | |
| 264 rect = containerOverflowRect; | |
| 265 EXPECT_TRUE(container->mapToVisualRectInAncestorSpace(&layoutView(), rect)); | |
| 266 EXPECT_EQ(LayoutRect(222, 111, 240, 110), rect); | |
| 267 } | |
| 268 | |
| 269 TEST_F(LayoutObjectTest, OverflowRectMappingWithContainerOverflowClip) | |
| 270 { | |
| 271 setBodyInnerHTML( | |
| 272 "<div id='container' style='position: absolute; top: 111px; left: 222px;
" | |
| 273 " border: 10px solid red; overflow: hidden; width: 50px; height: 80px
;'>" | |
| 274 " <div id='target' style='box-shadow: 40px 20px black; width: 100px;
height: 90px'></div>" | |
| 275 "</div>"); | |
| 276 | |
| 277 LayoutBlock* container = toLayoutBlock(getLayoutObjectByElementId("container
")); | |
| 278 EXPECT_EQ(LayoutUnit(0), container->scrollTop()); | |
| 279 EXPECT_EQ(LayoutUnit(0), container->scrollLeft()); | |
| 280 container->setScrollTop(LayoutUnit(7)); | |
| 281 container->setScrollLeft(LayoutUnit(8)); | |
| 282 | |
| 283 LayoutBlock* target = toLayoutBlock(getLayoutObjectByElementId("target")); | |
| 284 LayoutRect targetOverflowRect = target->localOverflowRectForPaintInvalidatio
n(); | |
| 285 // 140 = width(100) + box_shadow_offset_x(40) | |
| 286 // 110 = height(90) + box_shadow_offset_y(20) | |
| 287 EXPECT_EQ(LayoutRect(0, 0, 140, 110), targetOverflowRect); | |
| 288 LayoutRect rect = targetOverflowRect; | |
| 289 EXPECT_TRUE(target->mapToVisualRectInAncestorSpace(target, rect)); | |
| 290 EXPECT_EQ(LayoutRect(0, 0, 140, 110), rect); | |
| 291 | |
| 292 rect = targetOverflowRect; | |
| 293 EXPECT_TRUE(target->mapToVisualRectInAncestorSpace(container, rect)); | |
| 294 // 2 = target_x(0) + container_border_left(10) - scroll_left(8) | |
| 295 // 3 = target_y(0) + container_border_top(10) - scroll_top(7) | |
| 296 // Rect is not clipped by container's overflow clip. | |
| 297 EXPECT_EQ(LayoutRect(2, 3, 140, 110), rect); | |
| 298 | |
| 299 rect = targetOverflowRect; | |
| 300 EXPECT_TRUE(target->mapToVisualRectInAncestorSpace(&layoutView(), rect)); | |
| 301 // (2, 3, 140, 100) is first clipped by container's overflow clip, to (10, 1
0, 50, 80), | |
| 302 // then is by added container's offset in LayoutView (111, 222). | |
| 303 EXPECT_EQ(LayoutRect(232, 121, 50, 80), rect); | |
| 304 | |
| 305 LayoutRect containerOverflowRect = container->localOverflowRectForPaintInval
idation(); | |
| 306 // Because container has overflow clip, its visual overflow doesn't include
overflow from children. | |
| 307 // 70 = width(50) + border_left_width(10) + border_right_width(10) | |
| 308 // 100 = height(80) + border_top_width(10) + border_bottom_width(10) | |
| 309 EXPECT_EQ(LayoutRect(0, 0, 70, 100), containerOverflowRect); | |
| 310 rect = containerOverflowRect; | |
| 311 EXPECT_TRUE(container->mapToVisualRectInAncestorSpace(container, rect)); | |
| 312 // Container should not apply overflow clip on its own overflow rect. | |
| 313 EXPECT_EQ(LayoutRect(0, 0, 70, 100), rect); | |
| 314 | |
| 315 rect = containerOverflowRect; | |
| 316 EXPECT_TRUE(container->mapToVisualRectInAncestorSpace(&layoutView(), rect)); | |
| 317 EXPECT_EQ(LayoutRect(222, 111, 70, 100), rect); | |
| 318 } | |
| 319 | |
| 320 TEST_F(LayoutObjectTest, OverflowRectMappingWithContainerFlippedWritingModeAndOv
erflowClip) | |
| 321 { | |
| 322 setBodyInnerHTML( | |
| 323 "<div id='container' style='writing-mode: vertical-rl; position: absolut
e; top: 111px; left: 222px;" | |
| 324 " border: solid red; border-width: 10px 20px 30px 40px;" | |
| 325 " overflow: hidden; width: 50px; height: 80px'>" | |
| 326 " <div id='target' style='box-shadow: 40px 20px black; width: 100px;
height: 90px'></div>" | |
| 327 " <div style='width: 100px; height: 100px'></div>" | |
| 328 "</div>"); | |
| 329 | |
| 330 LayoutBlock* container = toLayoutBlock(getLayoutObjectByElementId("container
")); | |
| 331 EXPECT_EQ(LayoutUnit(0), container->scrollTop()); | |
| 332 // The initial scroll offset is to the left-most because of flipped blocks w
riting mode. | |
| 333 // 150 = total_layout_overflow(100 + 100) - width(50) | |
| 334 EXPECT_EQ(LayoutUnit(150), container->scrollLeft()); | |
| 335 container->setScrollTop(LayoutUnit(7)); | |
| 336 container->setScrollLeft(LayoutUnit(142)); // Scroll to the right by 8 pixel
s. | |
| 337 | |
| 338 LayoutBlock* target = toLayoutBlock(getLayoutObjectByElementId("target")); | |
| 339 LayoutRect targetOverflowRect = target->localOverflowRectForPaintInvalidatio
n(); | |
| 340 // -40 = -box_shadow_offset_x(40) (with target's top-right corner as the ori
gin) | |
| 341 // 140 = width(100) + box_shadow_offset_x(40) | |
| 342 // 110 = height(90) + box_shadow_offset_y(20) | |
| 343 EXPECT_EQ(LayoutRect(-40, 0, 140, 110), targetOverflowRect); | |
| 344 | |
| 345 LayoutRect rect = targetOverflowRect; | |
| 346 EXPECT_TRUE(target->mapToVisualRectInAncestorSpace(target, rect)); | |
| 347 // This rect is in physical coordinates of target. | |
| 348 EXPECT_EQ(LayoutRect(0, 0, 140, 110), rect); | |
| 349 | |
| 350 rect = targetOverflowRect; | |
| 351 EXPECT_TRUE(target->mapToVisualRectInAncestorSpace(container, rect)); | |
| 352 // -2 = target_physical_x(100) + container_border_left(40) - scroll_left(142
) | |
| 353 // 3 = target_y(0) + container_border_top(10) - scroll_top(7) | |
| 354 // Rect is not clipped by container's overflow clip. | |
| 355 EXPECT_EQ(LayoutRect(-2, 3, 140, 110), rect); | |
| 356 | |
| 357 rect = targetOverflowRect; | |
| 358 EXPECT_TRUE(target->mapToVisualRectInAncestorSpace(&layoutView(), rect)); | |
| 359 // (-2, 3, 140, 100) is first clipped by container's overflow clip, to (40,
10, 50, 80), | |
| 360 // then is added by container's offset in LayoutView (111, 222). | |
| 361 // TODO(crbug.com/600039): rect.x() should be 262 (left + border-left), but
is offset | |
| 362 // by extra horizontal border-widths because of layout error. | |
| 363 EXPECT_EQ(LayoutRect(322, 121, 50, 80), rect); | |
| 364 | |
| 365 LayoutRect containerOverflowRect = container->localOverflowRectForPaintInval
idation(); | |
| 366 // Because container has overflow clip, its visual overflow doesn't include
overflow from children. | |
| 367 // 110 = width(50) + border_left_width(40) + border_right_width(20) | |
| 368 // 120 = height(80) + border_top_width(10) + border_bottom_width(30) | |
| 369 EXPECT_EQ(LayoutRect(0, 0, 110, 120), containerOverflowRect); | |
| 370 | |
| 371 rect = containerOverflowRect; | |
| 372 EXPECT_TRUE(container->mapToVisualRectInAncestorSpace(container, rect)); | |
| 373 EXPECT_EQ(LayoutRect(0, 0, 110, 120), rect); | |
| 374 | |
| 375 rect = containerOverflowRect; | |
| 376 EXPECT_TRUE(container->mapToVisualRectInAncestorSpace(&layoutView(), rect)); | |
| 377 // TODO(crbug.com/600039): rect.x() should be 222 (left), but is offset by e
xtra horizontal | |
| 378 // border-widths because of layout error. | |
| 379 EXPECT_EQ(LayoutRect(282, 111, 110, 120), rect); | |
| 380 } | |
| 381 | |
| 382 } // namespace blink | 112 } // namespace blink |
| OLD | NEW |