Changeset 60761 in webkit
- Timestamp:
- Jun 6, 2010, 5:26:45 AM (14 years ago)
- Location:
- trunk
- Files:
-
- 3 added
- 18 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r60759 r60761 1 2010-06-06 Dirk Schulze <krit@webkit.org> 2 3 Reviewed by Nikolas Zimmermann. 4 5 hit testing does not respect clip paths 6 https://bugs.webkit.org/show_bug.cgi?id=15162 7 8 Two tests were incorrect, because of the assumption, that clipPath doesn't 9 influence hit testing. They needed an update. 10 The new test checks, that clipped areas don't throw a hit. 11 12 * svg/dynamic-updates/SVGClipPath-influences-hitTesting-expected.txt: Added. 13 * svg/dynamic-updates/SVGClipPath-influences-hitTesting.html: Added. 14 * svg/dynamic-updates/SVGClipPathElement-dom-clipPathUnits-attr-expected.txt: 15 * svg/dynamic-updates/SVGClipPathElement-svgdom-clipPathUnits-prop-expected.txt: 16 * svg/dynamic-updates/script-tests/SVGClipPath-influences-hitTesting.js: Added. 17 (executeBackgroundTest): 18 (executeTest): 19 * svg/dynamic-updates/script-tests/SVGClipPathElement-dom-clipPathUnits-attr.js: 20 (shouldBeEqualToString.executeTest): 21 * svg/dynamic-updates/script-tests/SVGClipPathElement-svgdom-clipPathUnits-prop.js: 22 (executeTest): 23 1 24 2010-06-06 Kent Tamura <tkent@chromium.org> 2 25 -
trunk/LayoutTests/svg/dynamic-updates/SVGClipPathElement-dom-clipPathUnits-attr-expected.txt
r30635 r60761 6 6 7 7 8 PASS clipPathElement.getAttribute('clipPathUnits') is "userSpaceOnUse" 8 9 PASS clipPathElement.getAttribute('clipPathUnits') is "objectBoundingBox" 9 PASS clipPathElement.getAttribute('clipPathUnits') is "userSpaceOnUse"10 10 PASS successfullyParsed is true 11 11 -
trunk/LayoutTests/svg/dynamic-updates/SVGClipPathElement-svgdom-clipPathUnits-prop-expected.txt
r30635 r60761 6 6 7 7 8 PASS clipPathElement.clipPathUnits.baseVal is SVGUnitTypes.SVG_UNIT_TYPE_USERSPACEONUSE 8 9 PASS clipPathElement.clipPathUnits.baseVal is SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX 9 PASS clipPathElement.clipPathUnits.baseVal is SVGUnitTypes.SVG_UNIT_TYPE_USERSPACEONUSE10 10 PASS successfullyParsed is true 11 11 -
trunk/LayoutTests/svg/dynamic-updates/script-tests/SVGClipPathElement-dom-clipPathUnits-attr.js
r48554 r60761 10 10 var clipPathElement = createSVGElement("clipPath"); 11 11 clipPathElement.setAttribute("id", "clipper"); 12 clipPathElement.setAttribute("clipPathUnits", " objectBoundingBox");12 clipPathElement.setAttribute("clipPathUnits", "userSpaceOnUse"); 13 13 14 var circleElement = createSVGElement("circle"); 15 circleElement.setAttribute("cx", "150"); 16 circleElement.setAttribute("cy", "150"); 17 circleElement.setAttribute("r", "150"); 18 clipPathElement.appendChild(circleElement); 14 var rectElementA = createSVGElement("rect"); 15 rectElementA.setAttribute("width", "10"); 16 rectElementA.setAttribute("height", "10"); 17 clipPathElement.appendChild(rectElementA); 19 18 20 19 defsElement.appendChild(clipPathElement); 21 20 22 var rectElement = createSVGElement("rect");23 rectElement .setAttribute("width", "300");24 rectElement .setAttribute("height", "300");25 rectElement .setAttribute("fill", "green");26 rectElement .setAttribute("clip-path", "url(#clipper)");27 rootSVGElement.appendChild(rectElement );21 var rectElementB = createSVGElement("rect"); 22 rectElementB.setAttribute("width", "100"); 23 rectElementB.setAttribute("height", "100"); 24 rectElementB.setAttribute("fill", "green"); 25 rectElementB.setAttribute("clip-path", "url(#clipper)"); 26 rootSVGElement.appendChild(rectElementB); 28 27 29 shouldBeEqualToString("clipPathElement.getAttribute('clipPathUnits')", " objectBoundingBox")28 shouldBeEqualToString("clipPathElement.getAttribute('clipPathUnits')", "userSpaceOnUse") 30 29 31 30 function executeTest() { 32 clipPathElement.setAttribute("clipPathUnits", " userSpaceOnUse");33 shouldBeEqualToString("clipPathElement.getAttribute('clipPathUnits')", " userSpaceOnUse");31 clipPathElement.setAttribute("clipPathUnits", "objectBoundingBox"); 32 shouldBeEqualToString("clipPathElement.getAttribute('clipPathUnits')", "objectBoundingBox"); 34 33 35 34 completeTest(); 36 35 } 37 36 38 startTest(rectElement , 150, 150);37 startTest(rectElementB, 5, 5); 39 38 40 39 var successfullyParsed = true; -
trunk/LayoutTests/svg/dynamic-updates/script-tests/SVGClipPathElement-svgdom-clipPathUnits-prop.js
r48554 r60761 10 10 var clipPathElement = createSVGElement("clipPath"); 11 11 clipPathElement.setAttribute("id", "clipper"); 12 clipPathElement.setAttribute("clipPathUnits", " objectBoundingBox");12 clipPathElement.setAttribute("clipPathUnits", "userSpaceOnUse"); 13 13 14 var circleElement = createSVGElement("circle"); 15 circleElement.setAttribute("cx", "150"); 16 circleElement.setAttribute("cy", "150"); 17 circleElement.setAttribute("r", "150"); 18 clipPathElement.appendChild(circleElement); 14 var rectElementA = createSVGElement("rect"); 15 rectElementA.setAttribute("width", "10"); 16 rectElementA.setAttribute("height", "10"); 17 clipPathElement.appendChild(rectElementA); 19 18 20 defsElement.appendChild(clipPathElement); ;19 defsElement.appendChild(clipPathElement); 21 20 22 var rectElement = createSVGElement("rect");23 rectElement .setAttribute("width", "300");24 rectElement .setAttribute("height", "300");25 rectElement .setAttribute("fill", "green");26 rectElement .setAttribute("clip-path", "url(#clipper)");27 rootSVGElement.appendChild(rectElement );21 var rectElementB = createSVGElement("rect"); 22 rectElementB.setAttribute("width", "100"); 23 rectElementB.setAttribute("height", "100"); 24 rectElementB.setAttribute("fill", "green"); 25 rectElementB.setAttribute("clip-path", "url(#clipper)"); 26 rootSVGElement.appendChild(rectElementB); 28 27 29 shouldBe("clipPathElement.clipPathUnits.baseVal", "SVGUnitTypes.SVG_UNIT_TYPE_ OBJECTBOUNDINGBOX");28 shouldBe("clipPathElement.clipPathUnits.baseVal", "SVGUnitTypes.SVG_UNIT_TYPE_USERSPACEONUSE"); 30 29 31 30 function executeTest() { 32 clipPathElement.clipPathUnits.baseVal = SVGUnitTypes.SVG_UNIT_TYPE_ USERSPACEONUSE;33 shouldBe("clipPathElement.clipPathUnits.baseVal", "SVGUnitTypes.SVG_UNIT_TYPE_ USERSPACEONUSE");31 clipPathElement.clipPathUnits.baseVal = SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX; 32 shouldBe("clipPathElement.clipPathUnits.baseVal", "SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX"); 34 33 35 34 completeTest(); 36 35 } 37 36 38 startTest(rectElement , 150, 150);37 startTest(rectElementB, 5, 5); 39 38 40 39 var successfullyParsed = true; -
trunk/WebCore/ChangeLog
r60760 r60761 1 2010-06-06 Dirk Schulze <krit@webkit.org> 2 3 Reviewed by Nikolas Zimmermann. 4 5 hit testing does not respect clip paths 6 https://bugs.webkit.org/show_bug.cgi?id=15162 7 8 Test: svg/dynamic-updates/SVGClipPath-influences-hitTesting.html 9 10 Added a check, if a float point is not only in the shape/object boundaries 11 but also is not in the clipped away area of a clipPath. 12 13 * rendering/HitTestRequest.h: 14 (WebCore::HitTestRequest::): 15 (WebCore::HitTestRequest::svgClipContent): 16 * rendering/RenderPath.cpp: 17 (WebCore::RenderPath::fillContains): 18 (WebCore::RenderPath::nodeAtFloatPoint): 19 * rendering/RenderPath.h: 20 * rendering/RenderSVGContainer.cpp: 21 (WebCore::RenderSVGContainer::nodeAtFloatPoint): 22 * rendering/RenderSVGImage.cpp: 23 (WebCore::RenderSVGImage::nodeAtFloatPoint): 24 * rendering/RenderSVGResourceClipper.cpp: 25 (WebCore::RenderSVGResourceClipper::hitTestClipContent): 26 * rendering/RenderSVGResourceClipper.h: 27 * rendering/RenderSVGText.cpp: 28 (WebCore::RenderSVGText::nodeAtFloatPoint): 29 * rendering/SVGRenderSupport.cpp: 30 (WebCore::pointInClippingArea): 31 * rendering/SVGRenderSupport.h: 32 1 33 2010-06-06 Dirk Schulze <krit@webkit.org> 2 34 -
trunk/WebCore/rendering/HitTestRequest.h
r50583 r60761 28 28 public: 29 29 enum RequestType { 30 ReadOnly = 0x1, 31 Active = 0x2, 32 MouseMove = 0x4, 33 MouseUp = 0x8, 34 IgnoreClipping = 0x10 30 ReadOnly = 1 << 1, 31 Active = 1 << 2, 32 MouseMove = 1 << 3, 33 MouseUp = 1 << 4, 34 IgnoreClipping = 1 << 5, 35 SVGClipContent = 1 << 6 35 36 }; 36 37 … … 45 46 bool mouseUp() const { return m_requestType & MouseUp; } 46 47 bool ignoreClipping() const { return m_requestType & IgnoreClipping; } 48 bool svgClipContent() const { return m_requestType & SVGClipContent; } 47 49 48 50 private: -
trunk/WebCore/rendering/PointerEventsHitRules.cpp
r50583 r60761 23 23 namespace WebCore { 24 24 25 PointerEventsHitRules::PointerEventsHitRules(EHitTesting hitTesting, EPointerEvents pointerEvents)25 PointerEventsHitRules::PointerEventsHitRules(EHitTesting hitTesting, const HitTestRequest& request, EPointerEvents pointerEvents) 26 26 : requireVisible(false) 27 27 , requireFill(false) … … 30 30 , canHitFill(false) 31 31 { 32 if (request.svgClipContent()) 33 pointerEvents = PE_FILL; 34 32 35 if (hitTesting == SVG_PATH_HITTESTING) { 33 36 switch (pointerEvents) -
trunk/WebCore/rendering/PointerEventsHitRules.h
r50583 r60761 21 21 #define PointerEventsHitRules_h 22 22 23 #include "HitTestRequest.h" 23 24 #include "RenderStyleConstants.h" 24 25 … … 33 34 }; 34 35 35 PointerEventsHitRules(EHitTesting, EPointerEvents);36 PointerEventsHitRules(EHitTesting, const HitTestRequest&, EPointerEvents); 36 37 37 38 bool requireVisible; -
trunk/WebCore/rendering/RenderPath.cpp
r60541 r60761 31 31 #include "FloatQuad.h" 32 32 #include "GraphicsContext.h" 33 #include "HitTestRequest.h" 33 34 #include "PointerEventsHitRules.h" 34 35 #include "RenderSVGContainer.h" … … 72 73 } 73 74 74 bool RenderPath::fillContains(const FloatPoint& point, bool requiresFill ) const75 bool RenderPath::fillContains(const FloatPoint& point, bool requiresFill, WindRule fillRule) const 75 76 { 76 77 if (!m_fillBoundingBox.contains(point)) … … 80 81 return false; 81 82 82 return m_path.contains(point, style()->svgStyle()->fillRule());83 return m_path.contains(point, fillRule); 83 84 } 84 85 … … 196 197 } 197 198 198 bool RenderPath::nodeAtFloatPoint(const HitTestRequest& , HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction)199 bool RenderPath::nodeAtFloatPoint(const HitTestRequest& request, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction) 199 200 { 200 201 // We only draw in the forground phase, so we only hit-test then. … … 204 205 FloatPoint localPoint = m_localTransform.inverse().mapPoint(pointInParent); 205 206 206 PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_PATH_HITTESTING, style()->pointerEvents()); 207 207 if (!pointInClippingArea(this, localPoint)) 208 return false; 209 210 PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_PATH_HITTESTING, request, style()->pointerEvents()); 208 211 bool isVisible = (style()->visibility() == VISIBLE); 209 212 if (isVisible || !hitRules.requireVisible) { 210 if ((hitRules.canHitStroke && (style()->svgStyle()->hasStroke() || !hitRules.requireStroke) && strokeContains(localPoint, hitRules.requireStroke)) 211 || (hitRules.canHitFill && (style()->svgStyle()->hasFill() || !hitRules.requireFill) && fillContains(localPoint, hitRules.requireFill))) { 213 const SVGRenderStyle* svgStyle = style()->svgStyle(); 214 WindRule fillRule = svgStyle->fillRule(); 215 if (request.svgClipContent()) 216 fillRule = svgStyle->clipRule(); 217 if ((hitRules.canHitStroke && (svgStyle->hasStroke() || !hitRules.requireStroke) && strokeContains(localPoint, hitRules.requireStroke)) 218 || (hitRules.canHitFill && (svgStyle->hasFill() || !hitRules.requireFill) && fillContains(localPoint, hitRules.requireFill, fillRule))) { 212 219 updateHitTestResult(result, roundedIntPoint(localPoint)); 213 220 return true; 214 221 } 215 222 } 216 217 223 return false; 218 224 } -
trunk/WebCore/rendering/RenderPath.h
r58570 r60761 48 48 private: 49 49 // Hit-detection seperated for the fill and the stroke 50 bool fillContains(const FloatPoint&, bool requiresFill = true ) const;50 bool fillContains(const FloatPoint&, bool requiresFill = true, WindRule fillRule = RULE_NONZERO) const; 51 51 bool strokeContains(const FloatPoint&, bool requiresStroke = true) const; 52 52 -
trunk/WebCore/rendering/RenderSVGContainer.cpp
r60541 r60761 160 160 FloatPoint localPoint = localToParentTransform().inverse().mapPoint(pointInParent); 161 161 162 if (!pointInClippingArea(this, localPoint)) 163 return false; 164 162 165 for (RenderObject* child = lastChild(); child; child = child->previousSibling()) { 163 166 if (child->nodeAtFloatPoint(request, result, localPoint, hitTestAction)) { -
trunk/WebCore/rendering/RenderSVGImage.cpp
r60541 r60761 113 113 } 114 114 115 bool RenderSVGImage::nodeAtFloatPoint(const HitTestRequest& , HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction)115 bool RenderSVGImage::nodeAtFloatPoint(const HitTestRequest& request, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction) 116 116 { 117 117 // We only draw in the forground phase, so we only hit-test then. … … 119 119 return false; 120 120 121 PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_IMAGE_HITTESTING, style()->pointerEvents()); 122 121 PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_IMAGE_HITTESTING, request, style()->pointerEvents()); 123 122 bool isVisible = (style()->visibility() == VISIBLE); 124 123 if (isVisible || !hitRules.requireVisible) { 125 124 FloatPoint localPoint = localToParentTransform().inverse().mapPoint(pointInParent); 125 126 if (!pointInClippingArea(this, localPoint)) 127 return false; 126 128 127 129 if (hitRules.canHitFill) { -
trunk/WebCore/rendering/RenderSVGResourceClipper.cpp
r60541 r60761 28 28 #include "FloatRect.h" 29 29 #include "GraphicsContext.h" 30 #include "HitTestRequest.h" 31 #include "HitTestResult.h" 30 32 #include "ImageBuffer.h" 31 33 #include "IntRect.h" … … 267 269 } 268 270 271 bool RenderSVGResourceClipper::hitTestClipContent(const FloatRect& objectBoundingBox, const FloatPoint& nodeAtPoint) 272 { 273 FloatPoint point = nodeAtPoint; 274 if (!pointInClippingArea(this, point)) 275 return false; 276 277 if (static_cast<SVGClipPathElement*>(node())->clipPathUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) { 278 AffineTransform transform; 279 transform.translate(objectBoundingBox.x(), objectBoundingBox.y()); 280 transform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height()); 281 point = transform.inverse().mapPoint(point); 282 } 283 284 for (Node* childNode = node()->firstChild(); childNode; childNode = childNode->nextSibling()) { 285 RenderObject* renderer = childNode->renderer(); 286 if (!childNode->isSVGElement() || !static_cast<SVGElement*>(childNode)->isStyled() || !renderer) 287 continue; 288 if (!renderer->isRenderPath() && !renderer->isSVGText() && !renderer->isSVGShadowTreeRootContainer()) 289 continue; 290 IntPoint hitPoint; 291 HitTestResult result(hitPoint); 292 if (renderer->nodeAtFloatPoint(HitTestRequest(HitTestRequest::SVGClipContent), result, point, HitTestForeground)) 293 return true; 294 } 295 296 return false; 297 } 298 269 299 FloatRect RenderSVGResourceClipper::resourceBoundingBox(RenderObject* object) 270 300 { -
trunk/WebCore/rendering/RenderSVGResourceClipper.h
r60541 r60761 55 55 56 56 virtual RenderSVGResourceType resourceType() const { return ClipperResourceType; } 57 58 bool hitTestClipContent(const FloatRect&, const FloatPoint&); 57 59 58 60 SVGUnitTypes::SVGUnitType clipPathUnits() const { return toUnitType(static_cast<SVGClipPathElement*>(node())->clipPathUnits()); } -
trunk/WebCore/rendering/RenderSVGText.cpp
r60541 r60761 34 34 #include "FloatQuad.h" 35 35 #include "GraphicsContext.h" 36 #include "HitTestRequest.h" 36 37 #include "PointerEventsHitRules.h" 37 38 #include "RenderLayer.h" … … 99 100 bool RenderSVGText::nodeAtFloatPoint(const HitTestRequest& request, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction) 100 101 { 101 PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_TEXT_HITTESTING, style()->pointerEvents());102 PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_TEXT_HITTESTING, request, style()->pointerEvents()); 102 103 bool isVisible = (style()->visibility() == VISIBLE); 103 104 if (isVisible || !hitRules.requireVisible) { … … 105 106 || (hitRules.canHitFill && (style()->svgStyle()->hasFill() || !hitRules.requireFill))) { 106 107 FloatPoint localPoint = localToParentTransform().inverse().mapPoint(pointInParent); 108 109 if (!pointInClippingArea(this, localPoint)) 110 return false; 111 107 112 return RenderBlock::nodeAtPoint(request, result, (int)localPoint.x(), (int)localPoint.y(), 0, 0, hitTestAction); 108 113 } -
trunk/WebCore/rendering/SVGRenderSupport.cpp
r60689 r60761 315 315 } 316 316 317 bool pointInClippingArea(const RenderObject* object, const FloatPoint& point) 318 { 319 ASSERT(object); 320 ASSERT(object->style()); 321 322 Document* document = object->document(); 323 ASSERT(document); 324 325 const SVGRenderStyle* svgStyle = object->style()->svgStyle(); 326 ASSERT(svgStyle); 327 328 // We just take clippers into account to determine if a point is on the node. The Specification may 329 // change later and we also need to check maskers. 330 if (svgStyle->hasClipper()) { 331 if (RenderSVGResourceClipper* clipper = getRenderSVGResourceById<RenderSVGResourceClipper>(document, svgStyle->clipperResource())) 332 return clipper->hitTestClipContent(object->objectBoundingBox(), point); 333 } 334 335 return true; 336 } 337 317 338 void deregisterFromResources(RenderObject* object) 318 339 { -
trunk/WebCore/rendering/SVGRenderSupport.h
r60689 r60761 80 80 void renderSubtreeToImage(ImageBuffer*, RenderObject*); 81 81 82 bool pointInClippingArea(const RenderObject*, const FloatPoint&); 83 82 84 void deregisterFromResources(RenderObject*); 83 85 void clampImageBufferSizeToViewport(FrameView*, IntSize& imageBufferSize);
Note:
See TracChangeset
for help on using the changeset viewer.