Diff
Modified: trunk/LayoutTests/ChangeLog (117708 => 117709)
--- trunk/LayoutTests/ChangeLog 2012-05-20 19:10:28 UTC (rev 117708)
+++ trunk/LayoutTests/ChangeLog 2012-05-20 19:49:45 UTC (rev 117709)
@@ -1,3 +1,16 @@
+2012-05-20 Philip Rogers <[email protected]>
+
+ Fix hit testing on non-scaling strokes
+ https://bugs.webkit.org/show_bug.cgi?id=82628
+
+ Reviewed by Nikolas Zimmermann.
+
+ * platform/chromium/test_expectations.txt:
+ * platform/mac/Skipped:
+ * svg/custom/non-scaling-stroke-expected.txt:
+ * svg/hittest/svg-shapes-non-scale-stroke-expected.txt: Added.
+ * svg/hittest/svg-shapes-non-scale-stroke.html: Added.
+
2012-05-19 Joshua Bell <[email protected]>
IndexedDB layout tests should make better use of test library functions
Modified: trunk/LayoutTests/platform/chromium/test_expectations.txt (117708 => 117709)
--- trunk/LayoutTests/platform/chromium/test_expectations.txt 2012-05-20 19:10:28 UTC (rev 117708)
+++ trunk/LayoutTests/platform/chromium/test_expectations.txt 2012-05-20 19:49:45 UTC (rev 117709)
@@ -1280,8 +1280,6 @@
BUGWK83875 LINUX : svg/text/font-size-below-point-five.svg = PASS TEXT
-BUGWK82628 : svg/hittest/svg-ellipse-non-scale-stroke.xhtml = FAIL
-
// It is very hard to see why some of these are failing. The diff must be tiny in some cases.
// Other fail intermittently in a way that is odd - clipping and masking should be stable.
// It is probably a test design flaw.
Modified: trunk/LayoutTests/platform/mac/Skipped (117708 => 117709)
--- trunk/LayoutTests/platform/mac/Skipped 2012-05-20 19:10:28 UTC (rev 117708)
+++ trunk/LayoutTests/platform/mac/Skipped 2012-05-20 19:49:45 UTC (rev 117709)
@@ -642,9 +642,6 @@
fast/repaint/scroll-relative-table-inside-table-cell.html
fast/table/cell-pref-width-invalidation.html
-# https://bugs.webkit.org/show_bug.cgi?id=82628
-svg/hittest/svg-ellipse-non-scale-stroke.xhtml
-
# The inner <input> should now grow to take the full cell's height.
fast/table/colspanMinWidth-vertical.html
Modified: trunk/LayoutTests/svg/custom/non-scaling-stroke-expected.txt (117708 => 117709)
--- trunk/LayoutTests/svg/custom/non-scaling-stroke-expected.txt 2012-05-20 19:10:28 UTC (rev 117708)
+++ trunk/LayoutTests/svg/custom/non-scaling-stroke-expected.txt 2012-05-20 19:49:45 UTC (rev 117709)
@@ -1,7 +1,7 @@
layer at (0,0) size 800x600
RenderView at (0,0) size 800x600
layer at (0,0) size 800x600
- RenderSVGRoot {svg} at (18,12) size 259x306
+ RenderSVGRoot {svg} at (12,0) size 287x488
RenderSVGHiddenContainer {defs} at (0,0) size 0x0
RenderSVGResourceLinearGradient {linearGradient} [id="grad1"] [gradientUnits=objectBoundingBox] [start=(0,0)] [end=(1,1)]
RenderSVGGradientStop {stop} [offset=0.00] [color=#0000FF]
@@ -15,14 +15,14 @@
RenderSVGRect {rect} at (0,10) size 10x10 [fill={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=10.00] [width=10.00] [height=10.00]
RenderSVGRect {rect} at (10,10) size 10x10 [fill={[type=SOLID] [color=#FFFF00]}] [x=10.00] [y=10.00] [width=10.00] [height=10.00]
RenderSVGRect {rect} at (0,0) size 400x50 [x=0.00] [y=0.00] [width=400.00] [height=50.00]
- RenderSVGContainer {g} at (18,12) size 104x66 [transform={m=((1.00,0.00)(0.00,1.00)) t=(20.00,20.00)}]
- RenderSVGRect {rect} at (18,12) size 104x66 [transform={m=((0.25,0.00)(0.00,1.00)) t=(0.00,0.00)}] [stroke={[type=LINEAR-GRADIENT] [id="grad1"] [stroke width=15.00]}] [x=0.00] [y=0.00] [width=400.00] [height=50.00]
- RenderSVGRect {rect} at (18,92) size 104x66 [transform={m=((0.25,0.00)(0.00,1.00)) t=(20.00,100.00)}] [stroke={[type=LINEAR-GRADIENT] [id="grad2"] [stroke width=15.00]}] [x=0.00] [y=0.00] [width=400.00] [height=50.00]
- RenderSVGContainer {use} at (18,172) size 104x66 [transform={m=((0.25,0.00)(0.00,1.00)) t=(20.00,180.00)}]
- RenderSVGRect {rect} at (18,172) size 104x66 [stroke={[type=PATTERN] [id="pattern"] [stroke width=15.00]}] [x=0.00] [y=0.00] [width=400.00] [height=50.00]
- RenderSVGContainer {use} at (18,252) size 104x66 [transform={m=((0.25,0.00)(0.00,1.00)) t=(20.00,260.00)}]
- RenderSVGRect {rect} at (18,252) size 104x66 [stroke={[type=SOLID] [color=#008000] [stroke width=15.00]}] [x=0.00] [y=0.00] [width=400.00] [height=50.00]
- RenderSVGContainer {use} at (156,12) size 121x66 [transform={m=((0.25,0.00)(0.25,1.00)) t=(160.00,20.00)}]
- RenderSVGRect {rect} at (156,12) size 121x66 [stroke={[type=SOLID] [color=#008000] [stroke width=15.00]}] [x=0.00] [y=0.00] [width=400.00] [height=50.00]
- RenderSVGContainer {use} at (158,89) size 104x217 [transform={m=((0.25,0.36)(0.00,1.00)) t=(160.00,100.00)}]
- RenderSVGRect {rect} at (158,89) size 104x217 [stroke={[type=SOLID] [color=#008000] [stroke width=15.00]}] [x=0.00] [y=0.00] [width=400.00] [height=50.00]
+ RenderSVGContainer {g} at (12,12) size 116x66 [transform={m=((1.00,0.00)(0.00,1.00)) t=(20.00,20.00)}]
+ RenderSVGRect {rect} at (12,12) size 116x66 [transform={m=((0.25,0.00)(0.00,1.00)) t=(0.00,0.00)}] [stroke={[type=LINEAR-GRADIENT] [id="grad1"] [stroke width=15.00]}] [x=0.00] [y=0.00] [width=400.00] [height=50.00]
+ RenderSVGRect {rect} at (12,92) size 116x66 [transform={m=((0.25,0.00)(0.00,1.00)) t=(20.00,100.00)}] [stroke={[type=LINEAR-GRADIENT] [id="grad2"] [stroke width=15.00]}] [x=0.00] [y=0.00] [width=400.00] [height=50.00]
+ RenderSVGContainer {use} at (12,172) size 116x66 [transform={m=((0.25,0.00)(0.00,1.00)) t=(20.00,180.00)}]
+ RenderSVGRect {rect} at (12,172) size 116x66 [stroke={[type=PATTERN] [id="pattern"] [stroke width=15.00]}] [x=0.00] [y=0.00] [width=400.00] [height=50.00]
+ RenderSVGContainer {use} at (12,252) size 116x66 [transform={m=((0.25,0.00)(0.00,1.00)) t=(20.00,260.00)}]
+ RenderSVGRect {rect} at (12,252) size 116x66 [stroke={[type=SOLID] [color=#008000] [stroke width=15.00]}] [x=0.00] [y=0.00] [width=400.00] [height=50.00]
+ RenderSVGContainer {use} at (134,12) size 165x66 [transform={m=((0.25,0.00)(0.25,1.00)) t=(160.00,20.00)}]
+ RenderSVGRect {rect} at (134,12) size 165x66 [stroke={[type=SOLID] [color=#008000] [stroke width=15.00]}] [x=0.00] [y=0.00] [width=400.00] [height=50.00]
+ RenderSVGContainer {use} at (152,0) size 116x488 [transform={m=((0.25,0.36)(0.00,1.00)) t=(160.00,100.00)}]
+ RenderSVGRect {rect} at (152,0) size 116x488 [stroke={[type=SOLID] [color=#008000] [stroke width=15.00]}] [x=0.00] [y=0.00] [width=400.00] [height=50.00]
Added: trunk/LayoutTests/svg/hittest/svg-shapes-non-scale-stroke-expected.txt (0 => 117709)
--- trunk/LayoutTests/svg/hittest/svg-shapes-non-scale-stroke-expected.txt (rev 0)
+++ trunk/LayoutTests/svg/hittest/svg-shapes-non-scale-stroke-expected.txt 2012-05-20 19:49:45 UTC (rev 117709)
@@ -0,0 +1,51 @@
+Tests for WK82628 - Make sure hit testing works properly on ellipses, rects, lines and curves with non-scaling stroke.
+
+On success, you will see a series of "PASS" messages and no "FAIL" messages.
+
+PASS ellipse1 stroke contains point at (29, 37)
+PASS ellipse2 stroke contains point at (279, 37)
+PASS ellipse1 stroke contains point at (34, 48)
+PASS ellipse2 stroke contains point at (284, 48)
+PASS ellipse1 stroke contains point at (94, 70)
+PASS ellipse2 stroke contains point at (344, 70)
+PASS ellipse1 stroke contains point at (100, 78)
+PASS ellipse2 stroke contains point at (350, 78)
+PASS ellipse1 stroke does not contain point at (33, 18)
+PASS ellipse2 stroke does not contain point at (283, 18)
+PASS ellipse1 stroke does not contain point at (81, 49)
+PASS ellipse2 stroke does not contain point at (331, 49)
+PASS ellipse1 stroke does not contain point at (129, 78)
+PASS ellipse2 stroke does not contain point at (379, 78)
+PASS rect1 stroke contains point at (172, 45)
+PASS rect2 stroke contains point at (422, 45)
+PASS rect1 stroke contains point at (183, 63)
+PASS rect2 stroke contains point at (433, 63)
+PASS rect1 stroke contains point at (220, 82)
+PASS rect2 stroke contains point at (470, 82)
+PASS rect1 stroke contains point at (233, 90)
+PASS rect2 stroke contains point at (483, 90)
+PASS rect1 stroke does not contain point at (205, 68)
+PASS rect2 stroke does not contain point at (455, 68)
+PASS line1 stroke contains point at (127, 97)
+PASS line2 stroke contains point at (377, 97)
+PASS line1 stroke contains point at (174, 146)
+PASS line2 stroke contains point at (424, 146)
+PASS line1 stroke does not contain point at (138, 131)
+PASS line2 stroke does not contain point at (388, 131)
+PASS line1 stroke does not contain point at (177, 126)
+PASS line2 stroke does not contain point at (427, 126)
+PASS curve1 stroke contains point at (24, 159)
+PASS curve2 stroke contains point at (274, 159)
+PASS curve1 stroke contains point at (107, 126)
+PASS curve2 stroke contains point at (357, 126)
+PASS curve1 stroke contains point at (169, 193)
+PASS curve2 stroke contains point at (419, 193)
+PASS curve1 stroke contains point at (195, 159)
+PASS curve2 stroke contains point at (445, 159)
+PASS curve1 stroke does not contain point at (5, 164)
+PASS curve2 stroke does not contain point at (255, 164)
+PASS curve1 stroke does not contain point at (81, 140)
+PASS curve2 stroke does not contain point at (331, 140)
+PASS curve1 stroke does not contain point at (161, 177)
+PASS curve2 stroke does not contain point at (411, 177)
+
Added: trunk/LayoutTests/svg/hittest/svg-shapes-non-scale-stroke.html (0 => 117709)
--- trunk/LayoutTests/svg/hittest/svg-shapes-non-scale-stroke.html (rev 0)
+++ trunk/LayoutTests/svg/hittest/svg-shapes-non-scale-stroke.html 2012-05-20 19:49:45 UTC (rev 117709)
@@ -0,0 +1,175 @@
+<html xmlns='http://www.w3.org/1999/xhtml'>
+ <head>
+ <style type="text/css">
+ #svgRoot {
+ margin: 0px;
+ padding: 0px;
+ position: absolute;
+ top: 0px;
+ left: 0px;
+ }
+ .nonscaletest {
+ stroke-width: 20px;
+ fill: #ccc;
+ fill-opacity: 0.4;
+ }
+ #ellipse1, #ellipse2 {
+ stroke: #f31900;
+ }
+ #line1, #line2 {
+ stroke: #3364c2;
+ }
+ #rect1, #rect2 {
+ stroke: #f7d72b;
+ }
+ #curve1, #curve2 {
+ stroke: #44c400;
+ }
+ </style>
+ <script type="text/_javascript_">
+ function enter(event) {
+ event.target.setAttribute("stroke-opacity", "0.4");
+ };
+ function exit(event) {
+ event.target.setAttribute("stroke-opacity", "0.7");
+ };
+ </script>
+ </head>
+ <body>
+ <p>Tests for WK82628 - Make sure hit testing works properly on ellipses, rects, lines and curves with non-scaling stroke.</p>
+ <p>On success, you will see a series of "PASS" messages and no "FAIL" messages.</p>
+ <pre id="console"></pre>
+
+ <svg id="svgRoot" width="500px" height="300px" viewBox="0 0 500 300" xmlns="http://www.w3.org/2000/svg">
+ <!-- The following are all small and scaled up -->
+ <g transform="translate(30, 0) scale(5, 5)">
+ <ellipse id="ellipse1" class="nonscaletest" cx="10" cy="10" rx="10" ry="5" vector-effect="non-scaling-stroke" pointer-events="visibleStroke" _onmouseover_="enter(evt)" _onmouseout_="exit(evt)" stroke-opacity="0.7" stroke-dasharray="15,25" stroke-linecap="round"/>
+ <rect id="rect1" class="nonscaletest" x="30" y="10" width="10" height="7" vector-effect="non-scaling-stroke" pointer-events="visibleStroke" _onmouseover_="enter(evt)" _onmouseout_="exit(evt)" stroke-opacity="0.7" stroke-dasharray="15,25" stroke-linecap="round"/>
+ <path id="line1" class="nonscaletest" d="M20 20 l 10 10z" vector-effect="non-scaling-stroke" pointer-events="visibleStroke" _onmouseover_="enter(evt)" _onmouseout_="exit(evt)" stroke-opacity="0.7" stroke-dasharray="15,25" stroke-linecap="round"/>
+ <g transform="translate(-6, 12)">
+ <path id="curve1" class="nonscaletest" d="M5,20 C10,10 25,10 25,20 S40,30 40,20" vector-effect="non-scaling-stroke" pointer-events="visibleStroke" _onmouseover_="enter(evt)" _onmouseout_="exit(evt)" stroke-opacity="0.7" stroke-dasharray="15,25" stroke-linecap="round"/>
+ </g>
+ </g>
+ <!-- The following are all large and scaled down -->
+ <g transform="translate(275, 0) scale(0.2, 0.2)">
+ <ellipse id="ellipse2" class="nonscaletest" cx="250" cy="250" rx="250" ry="125" vector-effect="non-scaling-stroke" pointer-events="visibleStroke" _onmouseover_="enter(evt)" class="nonscaletest" _onmouseout_="exit(evt)" stroke-opacity="0.7" stroke-dasharray="15,25" stroke-linecap="round"/>
+ <rect id="rect2" class="nonscaletest" x="750" y="250" width="250" height="175" vector-effect="non-scaling-stroke" pointer-events="visibleStroke" _onmouseover_="enter(evt)" _onmouseout_="exit(evt)" stroke-opacity="0.7" stroke-dasharray="15,25" stroke-linecap="round"/>
+ <path id="line2" class="nonscaletest" d="M500 500 l 250 250z" vector-effect="non-scaling-stroke" pointer-events="visibleStroke" _onmouseover_="enter(evt)" _onmouseout_="exit(evt)" stroke-opacity="0.7" stroke-dasharray="15,25" stroke-linecap="round"/>
+ <g transform="translate(-150, 300)">
+ <path id="curve2" class="nonscaletest" d="M125,500 C250,250 625,250 600,500 S1000,750 1000,500" vector-effect="non-scaling-stroke" pointer-events="visibleStroke" _onmouseover_="enter(evt)" _onmouseout_="exit(evt)" stroke-opacity="0.7" stroke-dasharray="15,25" stroke-linecap="round"/>
+ </g>
+ </g>
+ </svg>
+ <script type="text/_javascript_">
+ // document.body._onmousedown_ = function(evt) { console.log("mouse down at " + evt.x + "," + evt.y); }
+ if (window.layoutTestController)
+ layoutTestController.dumpAsText();
+
+ var resultString = "";
+ var ellipse1 = document.getElementById("ellipse1");
+ var ellipse2 = document.getElementById("ellipse2"); // 250px to the right of ellipse1
+ var pointsOnEllipse1Stroke = [
+ {x: 29, y: 37},
+ {x: 34, y: 48},
+ {x: 94, y: 70},
+ {x: 100, y: 78}
+ ];
+ var pointsNotOnEllipse1Stroke = [
+ {x: 33, y: 18},
+ {x: 81, y: 49},
+ {x: 129, y: 78}
+ ];
+
+ var rect1 = document.getElementById("rect1");
+ var rect2 = document.getElementById("rect2"); // 250px to the right of rect1
+ var pointsOnRect1Stroke = [
+ {x: 172, y: 45},
+ {x: 183, y: 63},
+ {x: 220, y: 82},
+ {x: 233, y: 90}
+ ];
+ var pointsNotOnRect1Stroke = [
+ {x: 205, y: 68}
+ ];
+
+ var line1 = document.getElementById("line1");
+ var line2 = document.getElementById("line2"); // 250px to the right of line1
+ var pointsOnLine1Stroke = [
+ {x: 127, y: 97},
+ {x: 174, y: 146}
+ ];
+ var pointsNotOnLine1Stroke = [
+ {x: 138, y: 131},
+ {x: 177, y: 126}
+ ];
+
+ var curve1 = document.getElementById("curve1");
+ var curve2 = document.getElementById("curve2"); // 250px to the right of curve1
+ var pointsOnCurve1Stroke = [
+ {x: 24, y: 159},
+ {x: 107, y: 126},
+ {x: 169, y: 193},
+ {x: 195, y: 159}
+ ];
+ var pointsNotOnCurve1Stroke = [
+ {x: 5, y: 164},
+ {x: 81, y: 140},
+ {x: 161, y: 177}
+ ];
+
+ pointsOnEllipse1Stroke.forEach( function(point) {
+ var pass = (ellipse1 == document.elementFromPoint(point.x, point.y));
+ resultString += ((pass) ? "PASS" : "FAIL") + " ellipse1 stroke contains point at (" + point.x + ", " + point.y + ")\n";
+ var pass = (ellipse2 == document.elementFromPoint(point.x + 250, point.y));
+ resultString += ((pass) ? "PASS" : "FAIL") + " ellipse2 stroke contains point at (" + (point.x+250) + ", " + point.y + ")\n";
+ });
+ pointsNotOnEllipse1Stroke.forEach( function(point) {
+ var pass = (ellipse1 != document.elementFromPoint(point.x, point.y));
+ resultString += ((pass) ? "PASS" : "FAIL") + " ellipse1 stroke does not contain point at (" + point.x + ", " + point.y + ")\n";
+ var pass = (ellipse2 != document.elementFromPoint(point.x + 250, point.y));
+ resultString += ((pass) ? "PASS" : "FAIL") + " ellipse2 stroke does not contain point at (" + (point.x+250) + ", " + point.y + ")\n";
+ });
+
+ pointsOnRect1Stroke.forEach( function(point) {
+ var pass = (rect1 == document.elementFromPoint(point.x, point.y));
+ resultString += ((pass) ? "PASS" : "FAIL") + " rect1 stroke contains point at (" + point.x + ", " + point.y + ")\n";
+ var pass = (rect2 == document.elementFromPoint(point.x + 250, point.y));
+ resultString += ((pass) ? "PASS" : "FAIL") + " rect2 stroke contains point at (" + (point.x+250) + ", " + point.y + ")\n";
+ });
+ pointsNotOnRect1Stroke.forEach( function(point) {
+ var pass = (rect1 != document.elementFromPoint(point.x, point.y));
+ resultString += ((pass) ? "PASS" : "FAIL") + " rect1 stroke does not contain point at (" + point.x + ", " + point.y + ")\n";
+ var pass = (rect2 != document.elementFromPoint(point.x + 250, point.y));
+ resultString += ((pass) ? "PASS" : "FAIL") + " rect2 stroke does not contain point at (" + (point.x+250) + ", " + point.y + ")\n";
+ });
+
+ pointsOnLine1Stroke.forEach( function(point) {
+ var pass = (line1 == document.elementFromPoint(point.x, point.y));
+ resultString += ((pass) ? "PASS" : "FAIL") + " line1 stroke contains point at (" + point.x + ", " + point.y + ")\n";
+ var pass = (line2 == document.elementFromPoint(point.x + 250, point.y));
+ resultString += ((pass) ? "PASS" : "FAIL") + " line2 stroke contains point at (" + (point.x+250) + ", " + point.y + ")\n";
+ });
+ pointsNotOnLine1Stroke.forEach( function(point) {
+ var pass = (line1 != document.elementFromPoint(point.x, point.y));
+ resultString += ((pass) ? "PASS" : "FAIL") + " line1 stroke does not contain point at (" + point.x + ", " + point.y + ")\n";
+ var pass = (line2 != document.elementFromPoint(point.x + 250, point.y));
+ resultString += ((pass) ? "PASS" : "FAIL") + " line2 stroke does not contain point at (" + (point.x+250) + ", " + point.y + ")\n";
+ });
+
+ pointsOnCurve1Stroke.forEach( function(point) {
+ var pass = (curve1 == document.elementFromPoint(point.x, point.y));
+ resultString += ((pass) ? "PASS" : "FAIL") + " curve1 stroke contains point at (" + point.x + ", " + point.y + ")\n";
+ var pass = (curve2 == document.elementFromPoint(point.x + 250, point.y));
+ resultString += ((pass) ? "PASS" : "FAIL") + " curve2 stroke contains point at (" + (point.x+250) + ", " + point.y + ")\n";
+ });
+ pointsNotOnCurve1Stroke.forEach( function(point) {
+ var pass = (curve1 != document.elementFromPoint(point.x, point.y));
+ resultString += ((pass) ? "PASS" : "FAIL") + " curve1 stroke does not contain point at (" + point.x + ", " + point.y + ")\n";
+ var pass = (curve2 != document.elementFromPoint(point.x + 250, point.y));
+ resultString += ((pass) ? "PASS" : "FAIL") + " curve2 stroke does not contain point at (" + (point.x+250) + ", " + point.y + ")\n";
+ });
+
+ document.getElementById("console").innerHTML = resultString;
+ </script>
+ </body>
+</html>
Modified: trunk/Source/WebCore/ChangeLog (117708 => 117709)
--- trunk/Source/WebCore/ChangeLog 2012-05-20 19:10:28 UTC (rev 117708)
+++ trunk/Source/WebCore/ChangeLog 2012-05-20 19:49:45 UTC (rev 117709)
@@ -1,3 +1,39 @@
+2012-05-20 Philip Rogers <[email protected]>
+
+ Fix hit testing on non-scaling strokes
+ https://bugs.webkit.org/show_bug.cgi?id=82628
+
+ Reviewed by Nikolas Zimmermann.
+
+ This change fixes hit testing on non-scaling strokes. It contains fixes for 3 bugs:
+ 1) RenderSVGRect::shapeDependentStrokeContains was not falling back to shape-based hit testing.
+ 2) m_strokeAndMarkerBoundingBox did not account for non-scaling strokes.
+ 3) RenderSVGShape::shapeDependentStrokeContains did not have any support for non-scaling strokes.
+
+ This change also contains some refactoring/cleanup of the non-scale-stroke codepaths.
+
+ Test: svg/hittest/svg-shapes-non-scale-stroke.html
+
+ * rendering/svg/RenderSVGEllipse.cpp:
+ (WebCore::RenderSVGEllipse::createShape):
+ * rendering/svg/RenderSVGRect.cpp:
+ (WebCore::RenderSVGRect::createShape):
+ (WebCore::RenderSVGRect::shapeDependentStrokeContains):
+ * rendering/svg/RenderSVGShape.cpp:
+ (WebCore::RenderSVGShape::shapeDependentStrokeContains):
+ (WebCore::RenderSVGShape::shapeDependentFillContains):
+ (WebCore::RenderSVGShape::nonScalingStrokePath):
+ (WebCore):
+ (WebCore::RenderSVGShape::setupNonScalingStrokeContext):
+ (WebCore::RenderSVGShape::nonScalingStrokeTransform):
+ (WebCore::RenderSVGShape::strokePath):
+ (WebCore::RenderSVGShape::fillAndStrokePath):
+ (WebCore::RenderSVGShape::updateCachedBoundaries):
+ (WebCore::RenderSVGShape::inflateWithStrokeAndMarkerBounds):
+ * rendering/svg/RenderSVGShape.h:
+ (WebCore::RenderSVGShape::hasNonScalingStroke):
+ (RenderSVGShape):
+
2012-05-19 Emil A Eklund <[email protected]>
Simplify RenderOverflow by using Rects
Modified: trunk/Source/WebCore/rendering/svg/RenderSVGEllipse.cpp (117708 => 117709)
--- trunk/Source/WebCore/rendering/svg/RenderSVGEllipse.cpp 2012-05-20 19:10:28 UTC (rev 117708)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGEllipse.cpp 2012-05-20 19:49:45 UTC (rev 117709)
@@ -55,7 +55,7 @@
m_radii = FloatSize();
// Fallback to RenderSVGShape if shape has a non scaling stroke.
- if (style()->svgStyle()->vectorEffect() == VE_NON_SCALING_STROKE) {
+ if (hasNonScalingStroke()) {
RenderSVGShape::createShape();
setIsPaintingFallback(true);
return;
Modified: trunk/Source/WebCore/rendering/svg/RenderSVGRect.cpp (117708 => 117709)
--- trunk/Source/WebCore/rendering/svg/RenderSVGRect.cpp 2012-05-20 19:10:28 UTC (rev 117708)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGRect.cpp 2012-05-20 19:49:45 UTC (rev 117709)
@@ -55,9 +55,8 @@
SVGRectElement* rect = static_cast<SVGRectElement*>(node());
ASSERT(rect);
- bool nonScalingStroke = style()->svgStyle()->vectorEffect() == VE_NON_SCALING_STROKE;
// Fallback to RenderSVGShape if rect has rounded corners.
- if (rect->hasAttribute(SVGNames::rxAttr) || rect->hasAttribute(SVGNames::ryAttr) || nonScalingStroke) {
+ if (rect->hasAttribute(SVGNames::rxAttr) || rect->hasAttribute(SVGNames::ryAttr) || hasNonScalingStroke()) {
RenderSVGShape::createShape();
setIsPaintingFallback(true);
return;
@@ -138,6 +137,9 @@
bool RenderSVGRect::shapeDependentStrokeContains(const FloatPoint& point) const
{
+ if (isPaintingFallback())
+ return RenderSVGShape::shapeDependentStrokeContains(point);
+
return m_outerStrokeRect.contains(point, FloatRect::InsideOrOnStroke) && !m_innerStrokeRect.contains(point, FloatRect::InsideButNotOnStroke);
}
Modified: trunk/Source/WebCore/rendering/svg/RenderSVGShape.cpp (117708 => 117709)
--- trunk/Source/WebCore/rendering/svg/RenderSVGShape.cpp 2012-05-20 19:10:28 UTC (rev 117708)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGShape.cpp 2012-05-20 19:49:45 UTC (rev 117709)
@@ -100,12 +100,22 @@
bool RenderSVGShape::shapeDependentStrokeContains(const FloatPoint& point) const
{
+ ASSERT(m_path);
BoundingRectStrokeStyleApplier applier(this, style());
+
+ if (hasNonScalingStroke()) {
+ AffineTransform nonScalingTransform = nonScalingStrokeTransform();
+ Path* usePath = nonScalingStrokePath(m_path.get(), nonScalingTransform);
+
+ return usePath->strokeContains(&applier, nonScalingTransform.mapPoint(point));
+ }
+
return m_path->strokeContains(&applier, point);
}
bool RenderSVGShape::shapeDependentFillContains(const FloatPoint& point, const WindRule fillRule) const
{
+ ASSERT(m_path);
return m_path->contains(point, fillRule);
}
@@ -197,6 +207,32 @@
setNeedsLayout(false);
}
+Path* RenderSVGShape::nonScalingStrokePath(const Path* path, const AffineTransform& strokeTransform) const
+{
+ DEFINE_STATIC_LOCAL(Path, tempPath, ());
+
+ tempPath = *path;
+ tempPath.transform(strokeTransform);
+
+ return &tempPath;
+}
+
+bool RenderSVGShape::setupNonScalingStrokeContext(AffineTransform& strokeTransform, GraphicsContextStateSaver& stateSaver)
+{
+ if (!strokeTransform.isInvertible())
+ return false;
+
+ stateSaver.save();
+ stateSaver.context()->concatCTM(strokeTransform.inverse());
+ return true;
+}
+
+AffineTransform RenderSVGShape::nonScalingStrokeTransform() const
+{
+ SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableElement*>(node());
+ return element->getScreenCTM(SVGLocatable::DisallowStyleUpdate);
+}
+
bool RenderSVGShape::shouldStrokeZeroLengthSubpath() const
{
// Spec(11.4): Any zero length subpath shall not be stroked if the "stroke-linecap" property has a value of butt
@@ -225,28 +261,6 @@
return &tempPath;
}
-Path* RenderSVGShape::nonScalingStrokePath(const Path* path, const AffineTransform& strokeTransform)
-{
- DEFINE_STATIC_LOCAL(Path, tempPath, ());
-
- tempPath = *path;
- tempPath.transform(strokeTransform);
-
- return &tempPath;
-}
-
-bool RenderSVGShape::setupNonScalingStrokeTransform(AffineTransform& strokeTransform, GraphicsContextStateSaver& stateSaver)
-{
- SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableElement*>(node());
- strokeTransform = element->getScreenCTM(SVGLocatable::DisallowStyleUpdate);
- if (!strokeTransform.isInvertible())
- return false;
-
- stateSaver.save();
- stateSaver.context()->concatCTM(strokeTransform.inverse());
- return true;
-}
-
void RenderSVGShape::fillShape(RenderStyle* style, GraphicsContext* context, Path* path, RenderSVGShape* shape)
{
Color fallbackColor;
@@ -263,25 +277,23 @@
}
void RenderSVGShape::strokePath(RenderStyle* style, GraphicsContext* context, Path* path, RenderSVGResource* strokePaintingResource,
- const Color& fallbackColor, bool nonScalingStroke, const AffineTransform& nonScalingStrokeTransform,
- int applyMode)
+ const Color& fallbackColor, int applyMode)
{
if (!style->svgStyle()->hasVisibleStroke())
return;
- Path* usePath = path;
- if (nonScalingStroke) {
- usePath = nonScalingStrokePath(path, nonScalingStrokeTransform);
- }
+
if (strokePaintingResource->applyResource(this, style, context, applyMode)) {
- strokePaintingResource->postApplyResource(this, context, applyMode, usePath, this);
+ strokePaintingResource->postApplyResource(this, context, applyMode, path, this);
return;
}
+
if (!fallbackColor.isValid())
return;
+
RenderSVGResourceSolidColor* fallbackResource = RenderSVGResource::sharedSolidPaintingResource();
fallbackResource->setColor(fallbackColor);
if (fallbackResource->applyResource(this, style, context, applyMode))
- fallbackResource->postApplyResource(this, context, applyMode, usePath, this);
+ fallbackResource->postApplyResource(this, context, applyMode, path, this);
}
void RenderSVGShape::fillAndStrokePath(GraphicsContext* context)
@@ -295,23 +307,27 @@
if (!strokePaintingResource)
return;
+ Path* usePath = m_path.get();
GraphicsContextStateSaver stateSaver(*context, false);
- AffineTransform nonScalingStrokeTransform;
- bool nonScalingStroke = style->svgStyle()->vectorEffect() == VE_NON_SCALING_STROKE;
- if (nonScalingStroke) {
- if (!setupNonScalingStrokeTransform(nonScalingStrokeTransform, stateSaver))
+ AffineTransform nonScalingTransform;
+
+ if (hasNonScalingStroke()) {
+ nonScalingTransform = nonScalingStrokeTransform();
+ if (!setupNonScalingStrokeContext(nonScalingTransform, stateSaver))
return;
+ usePath = nonScalingStrokePath(usePath, nonScalingTransform);
}
- strokePath(style, context, m_path.get(), strokePaintingResource, fallbackColor, nonScalingStroke, nonScalingStrokeTransform, ApplyToStrokeMode);
+ strokePath(style, context, usePath, strokePaintingResource, fallbackColor, ApplyToStrokeMode);
// Spec(11.4): Any zero length subpath shall not be stroked if the "stroke-linecap" property has a value of butt
// but shall be stroked if the "stroke-linecap" property has a value of round or square
for (size_t i = 0; i < m_zeroLengthLinecapLocations.size(); ++i) {
Path* usePath = zeroLengthLinecapPath(m_zeroLengthLinecapLocations[i]);
- strokePath(style, context, usePath, strokePaintingResource, fallbackColor, nonScalingStroke, nonScalingStrokeTransform, ApplyToFillMode);
+ if (hasNonScalingStroke())
+ usePath = nonScalingStrokePath(usePath, nonScalingTransform);
+ strokePath(style, context, usePath, strokePaintingResource, fallbackColor, ApplyToFillMode);
}
-
}
void RenderSVGShape::paint(PaintInfo& paintInfo, const LayoutPoint&)
@@ -423,6 +439,7 @@
m_fillBoundingBox = objectBoundingBox();
// Add zero-length sub-path linecaps to the fill box
+ // FIXME: zero-length subpaths do not respect vector-effect = non-scaling-stroke.
float strokeWidth = this->strokeWidth();
for (size_t i = 0; i < m_zeroLengthLinecapLocations.size(); ++i)
m_fillBoundingBox.unite(zeroLengthSubpathRect(m_zeroLengthLinecapLocations[i], strokeWidth));
@@ -449,7 +466,18 @@
FloatRect strokeRect;
if (svgStyle->hasStroke()) {
BoundingRectStrokeStyleApplier strokeStyle(this, style());
- m_strokeAndMarkerBoundingBox.unite(path().strokeBoundingRect(&strokeStyle));
+
+ // SVG1.2 Tiny only defines non scaling stroke for the stroke but not markers.
+ if (hasNonScalingStroke()) {
+ AffineTransform nonScalingTransform = nonScalingStrokeTransform();
+ if (nonScalingTransform.isInvertible()) {
+ Path* usePath = nonScalingStrokePath(m_path.get(), nonScalingTransform);
+ FloatRect strokeBoundingRect = usePath->strokeBoundingRect(&strokeStyle);
+ strokeBoundingRect = nonScalingTransform.inverse().mapRect(strokeBoundingRect);
+ m_strokeAndMarkerBoundingBox.unite(strokeBoundingRect);
+ }
+ } else
+ m_strokeAndMarkerBoundingBox.unite(path().strokeBoundingRect(&strokeStyle));
}
if (svgStyle->hasMarkers()) {
FloatRect markerBounds = calculateMarkerBoundsIfNeeded();
Modified: trunk/Source/WebCore/rendering/svg/RenderSVGShape.h (117708 => 117709)
--- trunk/Source/WebCore/rendering/svg/RenderSVGShape.h 2012-05-20 19:10:28 UTC (rev 117708)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGShape.h 2012-05-20 19:49:45 UTC (rev 117709)
@@ -97,6 +97,7 @@
void processZeroLengthSubpaths();
bool hasPath() const { return m_path.get(); }
+ bool hasNonScalingStroke() const { return style()->svgStyle()->vectorEffect() == VE_NON_SCALING_STROKE; }
private:
// Hit-detection separated for the fill and the stroke
@@ -118,15 +119,17 @@
void updateCachedBoundaries();
+ AffineTransform nonScalingStrokeTransform() const;
+ bool setupNonScalingStrokeContext(AffineTransform&, GraphicsContextStateSaver&);
+ Path* nonScalingStrokePath(const Path*, const AffineTransform&) const;
+
Path* zeroLengthLinecapPath(const FloatPoint&);
- bool setupNonScalingStrokeTransform(AffineTransform&, GraphicsContextStateSaver&);
- Path* nonScalingStrokePath(const Path*, const AffineTransform&);
bool shouldStrokeZeroLengthSubpath() const;
FloatRect zeroLengthSubpathRect(const FloatPoint&, float) const;
void fillShape(RenderStyle*, GraphicsContext*, Path*, RenderSVGShape*);
void strokePath(RenderStyle*, GraphicsContext*, Path*, RenderSVGResource*,
- const Color&, bool, const AffineTransform&, int);
+ const Color&, int);
void fillAndStrokePath(GraphicsContext*);
void inflateWithStrokeAndMarkerBounds();