Changeset 98361 in webkit
- Timestamp:
- Oct 25, 2011 10:54:11 AM (12 years ago)
- Location:
- trunk
- Files:
-
- 9 added
- 2 deleted
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r98359 r98361 1 2011-10-25 Simon Fraser <simon.fraser@apple.com> 2 3 REGRESSION (r88580): Cursor fails to change to pointer on embedded Google maps popups 4 https://bugs.webkit.org/show_bug.cgi?id=62797 5 6 Reviewed by Chris Marrin. 7 8 New tests for hit testing through various configurations of 3D transforms. 9 10 * platform/mac/transforms/3d/hit-testing/rotated-hit-test-expected.png: Removed. 11 * platform/mac/transforms/3d/hit-testing/rotated-hit-test-expected.txt: Removed. 12 * transforms/3d/hit-testing/composited-hit-test-expected.txt: Added. 13 * transforms/3d/hit-testing/composited-hit-test.html: Added. 14 * transforms/3d/hit-testing/resources/hit-test-utils.js: Added. 15 * transforms/3d/hit-testing/rotated-hit-test-expected.txt: Added. 16 * transforms/3d/hit-testing/rotated-hit-test-with-child-expected.txt: Added. 17 * transforms/3d/hit-testing/rotated-hit-test-with-child.html: Added. 18 * transforms/3d/hit-testing/rotated-hit-test.html: 19 * transforms/3d/hit-testing/rotated-hit-test2-expected.txt: Added. 20 * transforms/3d/hit-testing/rotated-hit-test2.html: Added. 21 1 22 2011-10-24 Jer Noble <jer.noble@apple.com> 2 23 -
trunk/LayoutTests/transforms/3d/hit-testing/rotated-hit-test.html
r41952 r98361 1 1 <html> 2 2 <head> 3 <title>Hit testing of almost edge-on elements</title> 4 <style type="text/css" media="screen"> 5 6 div:hover { 7 outline: 2px solid orange; 8 } 3 <style type="text/css"> 4 body { 5 margin: 0; 6 } 9 7 #container { 10 8 width: 200px; 11 9 height: 200px; 10 margin: 50px; 12 11 border: 1px solid black; 13 -webkit-perspective: 500 ;12 -webkit-perspective: 500px; 14 13 } 15 14 16 15 .box { 17 display: inline-block;16 position: absolute; 18 17 width: 200px; 19 18 height: 200px; 20 19 background-color: gray; 20 opacity: 0.75; 21 } 22 23 #left { 21 24 -webkit-transform-origin: 10% 50%; 22 25 -webkit-transform: rotateY(90deg); 23 26 } 27 28 #top { 29 -webkit-transform-origin: 50% 10%; 30 -webkit-transform: rotateX(-90deg); 31 } 32 33 #right { 34 -webkit-transform-origin: 90% 50%; 35 -webkit-transform: rotateY(-90deg); 36 } 37 38 #bottom { 39 -webkit-transform-origin: 50% 90%; 40 -webkit-transform: rotateX(90deg); 41 } 42 24 43 .box:hover { 25 44 background-color: orange; 26 45 } 27 46 </style> 28 <script type="text/javascript" charset="utf-8"> 29 function log(s) 30 { 31 var results = document.getElementById('results'); 32 results.innerHTML += s + '<br>'; 33 } 34 35 function runTest() 36 { 37 var firstHit = document.elementFromPoint(40, 150); 38 39 var box1 = document.getElementById('box1'); 40 var container = document.getElementById('container'); 41 42 if (firstHit == box1) 43 log('Found box1: PASS'); 44 else 45 log('Found ' + firstHit.id + ' : FAIL'); 46 } 47 47 <script src="resources/hit-test-utils.js"></script> 48 <script> 49 const hitTestData = [ 50 { 'point': [85, 100], 'target' : 'left' }, 51 { 'point': [155, 80], 'target' : 'top' }, 52 { 'point': [230, 80], 'target' : 'right' }, 53 { 'point': [155, 220], 'target' : 'bottom' }, 54 { 'point': [60, 60], 'target' : 'container' }, 55 { 'point': [100, 100], 'target' : 'container' }, 56 { 'point': [240, 240], 'target' : 'container' }, 57 { 'point': [200, 200], 'target' : 'container' }, 58 ]; 59 window.addEventListener('load', runTest, false); 48 60 </script> 49 61 </head> 50 <body onload="runTest()">62 <body> 51 63 52 64 <div id="container"> 53 <div class="box" id="box1"></div> 65 <div class="box" id="left"></div> 66 <div class="box" id="top"></div> 67 <div class="box" id="right"></div> 68 <div class="box" id="bottom"></div> 54 69 </div> 55 70 56 <div id="results"> 57 </div> 58 71 <div id="results"></div> 59 72 </body> 60 73 </html> -
trunk/Source/WebCore/ChangeLog
r98360 r98361 1 2011-10-25 Simon Fraser <simon.fraser@apple.com> 2 3 REGRESSION (r88580): Cursor fails to change to pointer on embedded Google maps popups 4 https://bugs.webkit.org/show_bug.cgi?id=62797 5 6 Reviewed by Chris Marrin. 7 8 When hit testing through transformed layers, RenderLayer would simply use 9 the composited bounds of the layer as the localHitTestRect for hit testing sublayers. 10 However, this broke hit testing on pages that have a composited, non-transformed layer 11 which falls outside the bounds of its parent, composited-transformed layer, like Google 12 Maps. 13 14 Fix by mapping the hitTestRect through transforms. However this is tricky, because 15 mapping a rect into the coordinate system of a layer can result in invalid rectangles 16 when point projection results in a negative w component. Fix TransformationMatrix::projectPoint() 17 to detect this case and replace X and Y with large values, and add boundsOfProjectedQuad(), which 18 maps rectangles with possibly-infinite location or bounds into rects which are representable 19 in an IntRect. 20 21 Tests: transforms/3d/hit-testing/composited-hit-test.html 22 transforms/3d/hit-testing/rotated-hit-test-with-child.html 23 transforms/3d/hit-testing/rotated-hit-test2.html 24 25 * platform/graphics/transforms/TransformationMatrix.cpp: 26 (WebCore::TransformationMatrix::projectPoint): 27 (WebCore::TransformationMatrix::projectQuad): 28 (WebCore::clampEdgeValue): 29 (WebCore::TransformationMatrix::boundsOfProjectedQuad): 30 * platform/graphics/transforms/TransformationMatrix.h: 31 * rendering/HitTestingTransformState.cpp: 32 (WebCore::HitTestingTransformState::boundsOfMappedQuad): 33 * rendering/HitTestingTransformState.h: 34 * rendering/RenderLayer.cpp: 35 (WebCore::RenderLayer::hitTestLayer): 36 1 37 2011-10-25 Adrienne Walker <enne@google.com> 2 38 -
trunk/Source/WebCore/platform/graphics/transforms/TransformationMatrix.cpp
r95901 r98361 37 37 #include <wtf/MathExtras.h> 38 38 39 using namespace std; 40 39 41 namespace WebCore { 40 42 … … 533 535 } 534 536 535 FloatPoint TransformationMatrix::projectPoint(const FloatPoint& p ) const537 FloatPoint TransformationMatrix::projectPoint(const FloatPoint& p, bool* clamped) const 536 538 { 537 539 // This is basically raytracing. We have a point in the destination … … 547 549 // 548 550 // d = -dot (Pn', R0) / dot (Pn', Rd) 551 if (clamped) 552 *clamped = false; 549 553 550 554 double x = p.x(); … … 552 556 double z = -(m13() * x + m23() * y + m43()) / m33(); 553 557 558 // FIXME: use multVecMatrix() 554 559 double outX = x * m11() + y * m21() + z * m31() + m41(); 555 560 double outY = x * m12() + y * m22() + z * m32() + m42(); 556 561 557 562 double w = x * m14() + y * m24() + z * m34() + m44(); 558 if (w != 1 && w != 0) { 563 if (w <= 0) { 564 outX = copysign(numeric_limits<int>::max(), outX); 565 outY = copysign(numeric_limits<int>::max(), outY); 566 if (clamped) 567 *clamped = true; 568 } else if (w != 1) { 559 569 outX /= w; 560 570 outY /= w; … … 571 581 projectedQuad.setP3(projectPoint(q.p3())); 572 582 projectedQuad.setP4(projectPoint(q.p4())); 583 573 584 return projectedQuad; 585 } 586 587 static float clampEdgeValue(float f) 588 { 589 ASSERT(!isnan(f)); 590 return min<float>(max<float>(f, -numeric_limits<int>::max() / 2), numeric_limits<int>::max() / 2); 591 } 592 593 IntRect TransformationMatrix::clampedBoundsOfProjectedQuad(const FloatQuad& q) const 594 { 595 FloatRect mappedQuadBounds = projectQuad(q).boundingBox(); 596 597 float left = clampEdgeValue(floorf(mappedQuadBounds.x())); 598 float top = clampEdgeValue(floorf(mappedQuadBounds.y())); 599 600 float right; 601 if (isinf(mappedQuadBounds.x()) && isinf(mappedQuadBounds.width())) 602 right = numeric_limits<int>::max() / 2; 603 else 604 right = clampEdgeValue(ceilf(mappedQuadBounds.maxX())); 605 606 float bottom; 607 if (isinf(mappedQuadBounds.y()) && isinf(mappedQuadBounds.height())) 608 bottom = numeric_limits<int>::max() / 2; 609 else 610 bottom = clampEdgeValue(ceilf(mappedQuadBounds.maxY())); 611 612 return IntRect(clampToInteger(left), clampToInteger(top), 613 clampToInteger(right - left), clampToInteger(bottom - top)); 574 614 } 575 615 -
trunk/Source/WebCore/platform/graphics/transforms/TransformationMatrix.h
r95901 r98361 157 157 // the local x,y position of the point where that ray intersects 158 158 // with the destination plane. 159 FloatPoint projectPoint(const FloatPoint& ) const;159 FloatPoint projectPoint(const FloatPoint&, bool* clamped = 0) const; 160 160 // Projects the four corners of the quad 161 161 FloatQuad projectQuad(const FloatQuad&) const; 162 // Projects the four corners of the quad and takes a bounding box, 163 // while sanitizing values created when the w component is negative. 164 IntRect clampedBoundsOfProjectedQuad(const FloatQuad&) const; 162 165 163 166 double m11() const { return m_matrix[0][0]; } -
trunk/Source/WebCore/rendering/HitTestingTransformState.cpp
r95901 r98361 74 74 } 75 75 76 IntRect HitTestingTransformState::boundsOfMappedQuad() const 77 { 78 return m_accumulatedTransform.inverse().clampedBoundsOfProjectedQuad(m_lastPlanarQuad); 79 } 80 76 81 } // namespace WebCore -
trunk/Source/WebCore/rendering/HitTestingTransformState.h
r95901 r98361 59 59 FloatPoint mappedPoint() const; 60 60 FloatQuad mappedQuad() const; 61 IntRect boundsOfMappedQuad() const; 61 62 void flatten(); 62 63 -
trunk/Source/WebCore/rendering/RenderLayer.cpp
r98060 r98361 3143 3143 // by our container. 3144 3144 LayoutPoint localPoint = roundedLayoutPoint(newTransformState->mappedPoint()); 3145 LayoutRect localHitTestRect; 3146 #if USE(ACCELERATED_COMPOSITING) 3147 if (isComposited()) { 3148 // It doesn't make sense to project hitTestRect into the plane of this layer, so use the same bounds we use for painting. 3149 localHitTestRect = backing()->compositedBounds(); 3150 } else 3151 #endif 3152 localHitTestRect = newTransformState->mappedQuad().enclosingBoundingBox(); 3145 LayoutRect localHitTestRect = newTransformState->boundsOfMappedQuad(); 3153 3146 3154 3147 // Now do a hit test with the root layer shifted to be us.
Note: See TracChangeset
for help on using the changeset viewer.