2006-09-26 Eric Seidel <eric@eseidel.com>
authoreseidel <eseidel@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 26 Sep 2006 12:50:16 +0000 (12:50 +0000)
committereseidel <eseidel@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 26 Sep 2006 12:50:16 +0000 (12:50 +0000)
        Reviewed by Tim H.

        RenderPath::nodeAtPoint does not respect stroke width
        http://bugzilla.opendarwin.org/show_bug.cgi?id=10829

        Test: svg/custom/stroke-width-click.svg

        * kcanvas/device/quartz/KCanvasItemQuartz.mm:
        (WebCore::RenderPath::strokeContains):
        * kcanvas/device/quartz/QuartzSupport.h:
        * kcanvas/device/quartz/QuartzSupport.mm:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@16574 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/svg/custom/stroke-width-click-expected.txt [new file with mode: 0644]
LayoutTests/svg/custom/stroke-width-click.svg [new file with mode: 0644]
WebCore/ChangeLog
WebCore/kcanvas/device/quartz/KCanvasItemQuartz.mm
WebCore/kcanvas/device/quartz/QuartzSupport.h
WebCore/kcanvas/device/quartz/QuartzSupport.mm

index eda76c463cb37f81e4040698019d3ff30c6ac5de..6b5c0f1d5eb66432990fd2b70e593beef718685f 100644 (file)
@@ -1,3 +1,13 @@
+2006-09-26  Eric Seidel  <eric@eseidel.com>
+
+        Reviewed by Tim H.
+        
+        RenderPath::nodeAtPoint does not respect stroke width
+        http://bugzilla.opendarwin.org/show_bug.cgi?id=10829
+
+        * svg/custom/stroke-width-click-expected.txt: Added.
+        * svg/custom/stroke-width-click.svg: Added.
+
 2006-09-25  Justin Garcia  <justin.garcia@apple.com>
 
         Reviewed by john
diff --git a/LayoutTests/svg/custom/stroke-width-click-expected.txt b/LayoutTests/svg/custom/stroke-width-click-expected.txt
new file mode 100644 (file)
index 0000000..5297040
--- /dev/null
@@ -0,0 +1,106 @@
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of body > html > foreignObject > svg > #document to 0 of body > html > foreignObject > svg > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of body > html > foreignObject > svg > #document to 0 of body > html > foreignObject > svg > #document toDOMRange:range from 39 of #text > div > div > body > html > foreignObject > svg > #document to 46 of #text > div > div > body > html > foreignObject > svg > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 39 of #text > div > div > body > html > foreignObject > svg > #document to 46 of #text > div > div > body > html > foreignObject > svg > #document toDOMRange:range from 0 of #text > div > div > body > html > foreignObject > svg > #document to 35 of #text > div > div > body > html > foreignObject > svg > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of #text > div > div > body > html > foreignObject > svg > #document to 35 of #text > div > div > body > html > foreignObject > svg > #document toDOMRange:range from 0 of #text > div > div > body > html > foreignObject > svg > #document to 47 of #text > div > div > body > html > foreignObject > svg > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of #text > div > div > body > html > foreignObject > svg > #document to 47 of #text > div > div > body > html > foreignObject > svg > #document toDOMRange:range from 0 of #text > div > div > body > html > foreignObject > svg > #document to 34 of #text > div > div > body > html > foreignObject > svg > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of #text > div > div > body > html > foreignObject > svg > #document to 34 of #text > div > div > body > html > foreignObject > svg > #document toDOMRange:range from 0 of #text > div > div > body > html > foreignObject > svg > #document to 46 of #text > div > div > body > html > foreignObject > svg > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of #text > div > div > body > html > foreignObject > svg > #document to 46 of #text > div > div > body > html > foreignObject > svg > #document toDOMRange:range from 0 of #text > div > div > body > html > foreignObject > svg > #document to 35 of #text > div > div > body > html > foreignObject > svg > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of #text > div > div > body > html > foreignObject > svg > #document to 35 of #text > div > div > body > html > foreignObject > svg > #document toDOMRange:range from 0 of #text > div > div > body > html > foreignObject > svg > #document to 47 of #text > div > div > body > html > foreignObject > svg > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of #text > div > div > body > html > foreignObject > svg > #document to 47 of #text > div > div > body > html > foreignObject > svg > #document toDOMRange:range from 0 of #text > div > div > body > html > foreignObject > svg > #document to 36 of #text > div > div > body > html > foreignObject > svg > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of #text > div > div > body > html > foreignObject > svg > #document to 36 of #text > div > div > body > html > foreignObject > svg > #document toDOMRange:range from 0 of #text > div > div > body > html > foreignObject > svg > #document to 48 of #text > div > div > body > html > foreignObject > svg > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of #text > div > div > body > html > foreignObject > svg > #document to 48 of #text > div > div > body > html > foreignObject > svg > #document toDOMRange:range from 0 of #text > div > div > body > html > foreignObject > svg > #document to 35 of #text > div > div > body > html > foreignObject > svg > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of #text > div > div > body > html > foreignObject > svg > #document to 35 of #text > div > div > body > html > foreignObject > svg > #document toDOMRange:range from 0 of #text > div > div > body > html > foreignObject > svg > #document to 47 of #text > div > div > body > html > foreignObject > svg > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of #text > div > div > body > html > foreignObject > svg > #document to 47 of #text > div > div > body > html > foreignObject > svg > #document toDOMRange:range from 0 of #text > div > div > body > html > foreignObject > svg > #document to 36 of #text > div > div > body > html > foreignObject > svg > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+
+  
+  
+    if (window.layoutTestController)
+      layoutTestController.dumpAsText();
+    
+    function log(string) {
+      var newDiv = document.createElementNS("http://www.w3.org/1999/xhtml", "div");
+      newDiv.textContent = string;
+      document.getElementById('log').appendChild(newDiv);
+    }
+    
+    var lastEvent = null;
+    
+    function testClick(x, y, expected) {
+      eventSender.mouseMoveTo(x, y);
+      eventSender.mouseDown();
+      eventSender.mouseUp();
+      if (expected && lastEvent && lastEvent.clientX == x && lastEvent.clientY == y) {
+        log("SUCCESS: click received at: " + x + ", " + y);
+      } else if (!expected && !lastEvent) {
+        log("SUCCESS: click at " + x + ", " + y + " was correctly ignored");
+      } else if (expected && lastEvent) {
+        log("FAILURE: click received at: " + lastEvent.clientX + ", " + lastEvent.clientY + " but it was expected at: " + x + ", " + y);
+      } else if (!expected && lastEvent) {
+        log("FAILURE: UNEXPECTED click received at: " + lastEvent.clientX + ", " + lastEvent.clientY);
+      } else if (expected && !lastEvent) {
+        log("FAILURE: NO click received at: " + x + ", " + y);
+      } else {
+        log("LOGIC ERORR");
+      }
+      lastEvent = null;
+    }
+    
+    function gotClick(evt) {
+      lastEvent = evt;
+    }
+    
+    function gotMouseEvent(evt, type) {
+      if (!window.layoutTestController)
+        document.getElementById('mouseover-text').textContent = type + " at " + evt.clientX + ", " + evt.clientY;
+    }
+  
+    
+  
+  
+    
+      
+      SUCCESS: click at 10, 10 was correctly ignoredSUCCESS: click received at: 30, 100SUCCESS: click at 29, 100 was correctly ignoredSUCCESS: click received at: 30, 50SUCCESS: click at 30, 49 was correctly ignoredSUCCESS: click received at: 30, 150SUCCESS: click at 30, 151 was correctly ignoredSUCCESS: click received at: 300, 100SUCCESS: click at 301, 100 was correctly ignoredSUCCESS: click received at: 300, 50SUCCESS: click at 300, 49 was correctly ignoredSUCCESS: click received at: 300, 150SUCCESS: click at 300, 151 was correctly ignoredSUCCESS: click at 1000, 1000 was correctly ignored
+    
+  
+  
+  
+  
+  
+  
+  
+  
+  
+    if (window.eventSender) {
+      testClick(10, 10, false);
+      testClick(30, 100, true);
+      testClick(29, 100, false);
+      testClick(30, 50, true);
+      testClick(30, 49, false);
+      testClick(30, 150, true);
+      testClick(30, 151, false);
+      testClick(300, 100, true);
+      testClick(301, 100, false);
+      testClick(300, 50, true);
+      testClick(300, 49, false);
+      testClick(300, 150, true);
+      testClick(300, 151, false);
+      testClick(1000, 1000, false);
+    } else {
+      log("ERROR: window.eventSender not found!  This test must be run using DumpRenderTree.  Mousing over the yellow area will log however.");
+    }
+  
+  
+
diff --git a/LayoutTests/svg/custom/stroke-width-click.svg b/LayoutTests/svg/custom/stroke-width-click.svg
new file mode 100644 (file)
index 0000000..006f6f1
--- /dev/null
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg">
+  <script type="text/javascript">
+  <![CDATA[
+    if (window.layoutTestController)
+      layoutTestController.dumpAsText();
+    
+    function log(string) {
+      var newDiv = document.createElementNS("http://www.w3.org/1999/xhtml", "div");
+      newDiv.textContent = string;
+      document.getElementById('log').appendChild(newDiv);
+    }
+    
+    var lastEvent = null;
+    
+    function testClick(x, y, expected) {
+      eventSender.mouseMoveTo(x, y);
+      eventSender.mouseDown();
+      eventSender.mouseUp();
+      if (expected && lastEvent && lastEvent.clientX == x && lastEvent.clientY == y) {
+        log("SUCCESS: click received at: " + x + ", " + y);
+      } else if (!expected && !lastEvent) {
+        log("SUCCESS: click at " + x + ", " + y + " was correctly ignored");
+      } else if (expected && lastEvent) {
+        log("FAILURE: click received at: " + lastEvent.clientX + ", " + lastEvent.clientY + " but it was expected at: " + x + ", " + y);
+      } else if (!expected && lastEvent) {
+        log("FAILURE: UNEXPECTED click received at: " + lastEvent.clientX + ", " + lastEvent.clientY);
+      } else if (expected && !lastEvent) {
+        log("FAILURE: NO click received at: " + x + ", " + y);
+      } else {
+        log("LOGIC ERORR");
+      }
+      lastEvent = null;
+    }
+    
+    function gotClick(evt) {
+      lastEvent = evt;
+    }
+    
+    function gotMouseEvent(evt, type) {
+      if (!window.layoutTestController)
+        document.getElementById('mouseover-text').textContent = type + " at " + evt.clientX + ", " + evt.clientY;
+    }
+  ]]>
+  </script>  
+  <foreignObject y="200" width="600" height="400">
+  <html xmlns="http://www.w3.org/1999/xhtml">
+    <body>
+      <div id="log">
+      </div>
+    </body>
+  </html>
+  </foreignObject>
+  
+  <!-- Paths only seem to stroke from startX to endX - 1 pixels.  I was not aware of that before writing this test.  Firefox and Opera match our behavior -->
+  <path d="M 30 100 L 301 100" stroke-width="100" stroke="yellow" onclick="gotClick(evt)" onmouseover="gotMouseEvent(evt, 'mouseover')" onmouseout="gotMouseEvent(evt, 'mouseout')" onmousemove="gotMouseEvent(evt, 'mousemove')" />
+  <text id="mouseover-text" x="30" y="190"></text>
+  
+  <script type="text/javascript">
+  <![CDATA[
+    if (window.eventSender) {
+      testClick(10, 10, false);
+      testClick(30, 100, true);
+      testClick(29, 100, false);
+      testClick(30, 50, true);
+      testClick(30, 49, false);
+      testClick(30, 150, true);
+      testClick(30, 151, false);
+      testClick(300, 100, true);
+      testClick(301, 100, false);
+      testClick(300, 50, true);
+      testClick(300, 49, false);
+      testClick(300, 150, true);
+      testClick(300, 151, false);
+      testClick(1000, 1000, false);
+    } else {
+      log("ERROR: window.eventSender not found!  This test must be run using DumpRenderTree.  Mousing over the yellow area will log however.");
+    }
+  ]]>
+  </script>
+</svg>
index 59a6bd3f951e57f1e4eda76ebfb359fabc14f4d9..1c56f236e1b4413e8d642f38ad5ccb845cdd2dbd 100644 (file)
@@ -1,3 +1,17 @@
+2006-09-26  Eric Seidel  <eric@eseidel.com>
+
+        Reviewed by Tim H.
+        
+        RenderPath::nodeAtPoint does not respect stroke width
+        http://bugzilla.opendarwin.org/show_bug.cgi?id=10829
+
+        Test: svg/custom/stroke-width-click.svg
+
+        * kcanvas/device/quartz/KCanvasItemQuartz.mm:
+        (WebCore::RenderPath::strokeContains):
+        * kcanvas/device/quartz/QuartzSupport.h:
+        * kcanvas/device/quartz/QuartzSupport.mm:
+
 2006-09-26  Eric Seidel  <eric@eseidel.com>
 
         Reviewed by mitz.
index 492418d2c1fff78182a7c070acbfb4afe5bf88de..64daab69c402f4896606b3a5bf2e025d0b130ef3 100644 (file)
@@ -68,7 +68,17 @@ bool RenderPath::strokeContains(const FloatPoint& point, bool requiresStroke) co
         return false;
 
     CGMutablePathRef cgPath = path().platformPath();
-    return pathContainsPoint(cgPath, point, kCGPathStroke);
+    
+    CGContextRef context = scratchContext();
+    CGContextSaveGState(context);
+    
+    CGContextBeginPath(context);
+    CGContextAddPath(context, cgPath);
+    applyStrokeStyleToContext(context, style(), this);
+    bool hitSuccess = CGContextPathContainsPoint(context, point, kCGPathStroke);
+    CGContextRestoreGState(context);
+    
+    return hitSuccess;
 }
 
 }
index 943bf1d52ea9dd92aa0b6c9749c25068c3f8c4eb..576768883c66e44978f86c5db2ec14ca88ed20a1 100644 (file)
@@ -46,8 +46,8 @@ CGAffineTransform CGAffineTransformMakeMapBetweenRects(CGRect source, CGRect des
 void applyStrokeStyleToContext(CGContextRef, const KRenderingStrokePainter&);
 void applyStrokeStyleToContext(CGContextRef, RenderStyle*, const RenderObject*);
 
-FloatRect strokeBoundingBox(const Path&, const KRenderingStrokePainter&);
-bool pathContainsPoint(CGMutablePathRef, const FloatPoint&, CGPathDrawingMode);
+CGContextRef scratchContext();
+FloatRect strokeBoundingBox(const Path& path, const KRenderingStrokePainter&);
 
 static inline CGLineCap CGLineCapFromKC(KCCapStyle cap)
 {
index 860e4ef102c6bfcf3d44be823ad00861d7aa43ab..f9e4f05a4de567694592e82de79a1c18bcbd7ef0 100644 (file)
@@ -129,20 +129,6 @@ FloatRect strokeBoundingBox(const Path& path, const KRenderingStrokePainter& str
     return FloatRect(box);
 }
 
-bool pathContainsPoint(CGMutablePathRef cgPath, const FloatPoint& point, CGPathDrawingMode drawMode)
-{
-   CGContextRef context = scratchContext();
-   CGContextSaveGState(context);
-   
-   CGContextBeginPath(context);
-   CGContextAddPath(context, cgPath);
-   bool hitSuccess = CGContextPathContainsPoint(context, point, drawMode);
-
-   CGContextRestoreGState(context);
-
-   return hitSuccess;
-}
-
 }
 
 #endif // SVG_SUPPORT