Commit e9bd34c6 authored by Fredrik Söderquist's avatar Fredrik Söderquist Committed by Commit Bot

Use approximate stroke bounding boxes for SVG shapes

This moves the stroke approximation code from
LayoutSVGPath::HitTestStrokeBoundingBox to a helper in LayoutSVGShape,
and then makes use of it in LayoutSVGShape::CalculateStrokeBoundingBox()
(which is the generic "stroke bounds" computation for shapes) as well.

This makes stroke bounding box computation O(1) (assuming a fill bbox
exists), avoiding the generation of a stroke path, which can be
expensive for the more "complex" parametrizations (primarily dashes.)

The downside is of course lower fidelity, and the approximation will
always be both larger than the fill bbox and larger than the "exact"
stroke bbox.

Also fix an issue where a miter-limit < 1 would incorrectly shrink the
resulting bounding box in some cases.

Bug: 435097
Cq-Include-Trybots: master.tryserver.chromium.linux:linux_layout_tests_slimming_paint_v2
Change-Id: Id0228bc78bb7d8db223be082106f3c3d2bcb038a
Reviewed-on: https://chromium-review.googlesource.com/774746
Commit-Queue: Fredrik Söderquist <fs@opera.com>
Reviewed-by: default avatarFlorin Malita <fmalita@chromium.org>
Cr-Commit-Position: refs/heads/master@{#518392}
parent fbcb74e2
...@@ -25,8 +25,8 @@ NoseY: 206 ...@@ -25,8 +25,8 @@ NoseY: 206
Mouth role: AXRole: AXButton Mouth role: AXRole: AXButton
Mouth label: smile Mouth label: smile
MouthX: 116 MouthX: 101
MouthY: 275 MouthY: 260
Text role: AXRole: AXStaticText Text role: AXRole: AXStaticText
......
...@@ -8,12 +8,12 @@ ...@@ -8,12 +8,12 @@
"paintInvalidations": [ "paintInvalidations": [
{ {
"object": "LayoutSVGPath path id='path'", "object": "LayoutSVGPath path id='path'",
"rect": [198, 198, 105, 105], "rect": [197, 197, 107, 107],
"reason": "appeared" "reason": "appeared"
}, },
{ {
"object": "LayoutSVGRoot svg", "object": "LayoutSVGRoot svg",
"rect": [98, 98, 104, 104], "rect": [97, 97, 106, 106],
"reason": "disappeared" "reason": "disappeared"
} }
] ]
......
...@@ -8,12 +8,12 @@ ...@@ -8,12 +8,12 @@
"paintInvalidations": [ "paintInvalidations": [
{ {
"object": "LayoutSVGPath path", "object": "LayoutSVGPath path",
"rect": [202, 211, 112, 112], "rect": [189, 197, 139, 139],
"reason": "style change" "reason": "style change"
}, },
{ {
"object": "LayoutSVGRoot svg id='svg-root'", "object": "LayoutSVGRoot svg id='svg-root'",
"rect": [202, 211, 112, 112], "rect": [189, 197, 139, 139],
"reason": "appeared" "reason": "appeared"
} }
] ]
......
...@@ -8,13 +8,13 @@ ...@@ -8,13 +8,13 @@
"paintInvalidations": [ "paintInvalidations": [
{ {
"object": "LayoutSVGPath path id='path'", "object": "LayoutSVGPath path id='path'",
"rect": [199, 49, 102, 52], "rect": [29, 29, 142, 92],
"reason": "disappeared" "reason": "appeared"
}, },
{ {
"object": "LayoutSVGPath path id='path'", "object": "LayoutSVGPath path id='path'",
"rect": [49, 49, 102, 52], "rect": [179, 29, 122, 92],
"reason": "appeared" "reason": "disappeared"
} }
] ]
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
"paintInvalidations": [ "paintInvalidations": [
{ {
"object": "LayoutSVGRoot svg", "object": "LayoutSVGRoot svg",
"rect": [264, 218, 164, 107], "rect": [253, 208, 184, 129],
"reason": "appeared" "reason": "appeared"
} }
] ]
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
"paintInvalidations": [ "paintInvalidations": [
{ {
"object": "LayoutSVGRoot svg", "object": "LayoutSVGRoot svg",
"rect": [264, 218, 164, 107], "rect": [253, 208, 184, 129],
"reason": "appeared" "reason": "appeared"
} }
] ]
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
"paintInvalidations": [ "paintInvalidations": [
{ {
"object": "LayoutSVGPath path id='path'", "object": "LayoutSVGPath path id='path'",
"rect": [121, 126, 68, 68], "rect": [113, 118, 84, 84],
"reason": "style change" "reason": "style change"
} }
] ]
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
"paintInvalidations": [ "paintInvalidations": [
{ {
"object": "LayoutSVGPath path id='go'", "object": "LayoutSVGPath path id='go'",
"rect": [89, 94, 100, 100], "rect": [89, 94, 108, 108],
"reason": "full" "reason": "full"
} }
] ]
......
...@@ -62,108 +62,113 @@ ...@@ -62,108 +62,113 @@
"reason": "appeared" "reason": "appeared"
}, },
{ {
"object": "LayoutSVGText text", "object": "LayoutSVGContainer use id='closeButtonnestedWindow'",
"rect": [615, 153, 14, 81], "rect": [374, 182, 15, 15],
"reason": "appeared" "reason": "appeared"
}, },
{ {
"object": "LayoutSVGContainer use id='closeButtonnavWindow'", "object": "LayoutSVGContainer use id='minimizeButtonnavWindow'",
"rect": [615, 83, 12, 12], "rect": [754, 94, 15, 13],
"reason": "paint property change"
},
{
"object": "LayoutSVGContainer use id='closeButtonnavWindow'",
"rect": [782, 94, 12, 11],
"reason": "appeared" "reason": "appeared"
}, },
{
"object": "LayoutSVGContainer use id='closeButtonnavWindow'",
"rect": [782, 94, 12, 11],
"reason": "paint property change"
},
{ {
"object": "LayoutSVGContainer use id='minimizeButtonnavWindow'", "object": "LayoutSVGContainer use id='minimizeButtonnavWindow'",
"rect": [615, 115, 12, 11], "rect": [754, 94, 15, 13],
"reason": "paint property change" "reason": "paint property change"
}, },
{ {
"object": "LayoutSVGContainer use id='maximizeButtonnavWindow'", "object": "LayoutSVGContainer use id='minimizeButtonbigWindow'",
"rect": [615, 99, 12, 11], "rect": [543, 145, 15, 13],
"reason": "paint property change" "reason": "appeared"
}, },
{ {
"object": "LayoutSVGContainer use id='closeButtonbigWindow'", "object": "LayoutSVGContainer use id='minimizeButtonstatusWindow'",
"rect": [571, 145, 12, 11], "rect": [361, 345, 15, 13],
"reason": "appeared" "reason": "appeared"
}, },
{ {
"object": "LayoutSVGContainer use id='minimizeButtonnestedWindow'", "object": "LayoutSVGContainer use id='minimizeButtoncolourPickerWindow'",
"rect": [349, 184, 12, 11], "rect": [207, 197, 15, 13],
"reason": "appeared" "reason": "appeared"
}, },
{ {
"object": "LayoutSVGContainer use id='closeButtoncolourPickerWindow'", "object": "LayoutSVGText text",
"rect": [235, 197, 12, 11], "rect": [615, 153, 14, 81],
"reason": "appeared" "reason": "appeared"
}, },
{ {
"object": "LayoutSVGContainer use id='maximizeButtonstatusWindow'", "object": "LayoutSVGContainer use id='closeButtonnavWindow'",
"rect": [376, 345, 11, 12], "rect": [781, 92, 14, 15],
"reason": "appeared" "reason": "appeared"
}, },
{ {
"object": "LayoutSVGContainer use id='minimizeButtonstatusWindow'", "object": "LayoutSVGContainer use id='closeButtonnavWindow'",
"rect": [363, 345, 11, 12], "rect": [781, 92, 14, 15],
"reason": "paint property change"
},
{
"object": "LayoutSVGContainer use id='closeButtonbigWindow'",
"rect": [570, 143, 14, 15],
"reason": "appeared" "reason": "appeared"
}, },
{ {
"object": "LayoutSVGContainer use id='maximizeButtonnavWindow'", "object": "LayoutSVGContainer use id='closeButtoncolourPickerWindow'",
"rect": [769, 94, 11, 11], "rect": [234, 195, 14, 15],
"reason": "appeared" "reason": "appeared"
}, },
{ {
"object": "LayoutSVGContainer use id='maximizeButtonnavWindow'", "object": "LayoutSVGContainer use id='closeButtonnavWindow'",
"rect": [769, 94, 11, 11], "rect": [614, 82, 14, 14],
"reason": "paint property change" "reason": "paint property change"
}, },
{ {
"object": "LayoutSVGContainer use id='minimizeButtonnavWindow'", "object": "LayoutSVGContainer use id='closeButtonsmallWindow'",
"rect": [756, 94, 11, 11], "rect": [453, 378, 14, 14],
"reason": "appeared" "reason": "appeared"
}, },
{ {
"object": "LayoutSVGContainer use id='minimizeButtonnavWindow'", "object": "LayoutSVGContainer use id='minimizeButtonnavWindow'",
"rect": [756, 94, 11, 11], "rect": [614, 115, 14, 13],
"reason": "paint property change" "reason": "paint property change"
}, },
{ {
"object": "LayoutSVGContainer use id='maximizeButtonbigWindow'", "object": "LayoutSVGContainer use id='minimizeButtonsmallWindow'",
"rect": [558, 145, 11, 11], "rect": [426, 379, 14, 13],
"reason": "appeared" "reason": "appeared"
}, },
{ {
"object": "LayoutSVGContainer use id='minimizeButtonbigWindow'", "object": "LayoutSVGContainer use id='minimizeButtonnestedWindow'",
"rect": [545, 145, 11, 11], "rect": [348, 184, 14, 13],
"reason": "appeared" "reason": "appeared"
}, },
{ {
"object": "LayoutSVGContainer use id='closeButtonsmallWindow'", "object": "LayoutSVGContainer use id='maximizeButtonnavWindow'",
"rect": [454, 379, 11, 11], "rect": [615, 99, 12, 11],
"reason": "paint property change"
},
{
"object": "LayoutSVGContainer use id='maximizeButtonstatusWindow'",
"rect": [376, 345, 11, 12],
"reason": "appeared" "reason": "appeared"
}, },
{ {
"object": "LayoutSVGContainer use id='maximizeButtonsmallWindow'", "object": "LayoutSVGContainer use id='maximizeButtonnavWindow'",
"rect": [441, 379, 11, 11], "rect": [769, 94, 11, 11],
"reason": "appeared" "reason": "appeared"
}, },
{ {
"object": "LayoutSVGContainer use id='minimizeButtonsmallWindow'", "object": "LayoutSVGContainer use id='maximizeButtonnavWindow'",
"rect": [428, 379, 11, 11], "rect": [769, 94, 11, 11],
"reason": "paint property change"
},
{
"object": "LayoutSVGContainer use id='maximizeButtonbigWindow'",
"rect": [558, 145, 11, 11],
"reason": "appeared" "reason": "appeared"
}, },
{ {
"object": "LayoutSVGContainer use id='closeButtonnestedWindow'", "object": "LayoutSVGContainer use id='maximizeButtonsmallWindow'",
"rect": [376, 184, 11, 11], "rect": [441, 379, 11, 11],
"reason": "appeared" "reason": "appeared"
}, },
{ {
...@@ -175,11 +180,6 @@ ...@@ -175,11 +180,6 @@
"object": "LayoutSVGContainer use id='maximizeButtoncolourPickerWindow'", "object": "LayoutSVGContainer use id='maximizeButtoncolourPickerWindow'",
"rect": [222, 197, 11, 11], "rect": [222, 197, 11, 11],
"reason": "appeared" "reason": "appeared"
},
{
"object": "LayoutSVGContainer use id='minimizeButtoncolourPickerWindow'",
"rect": [209, 197, 11, 11],
"reason": "appeared"
} }
] ]
} }
......
...@@ -8,12 +8,12 @@ ...@@ -8,12 +8,12 @@
"paintInvalidations": [ "paintInvalidations": [
{ {
"object": "LayoutSVGPath path id='path'", "object": "LayoutSVGPath path id='path'",
"rect": [98, 98, 104, 104], "rect": [197, 197, 107, 107],
"reason": "subtree" "reason": "subtree"
}, },
{ {
"object": "LayoutSVGPath path id='path'", "object": "LayoutSVGPath path id='path'",
"rect": [199, 199, 103, 103], "rect": [97, 97, 106, 106],
"reason": "subtree" "reason": "subtree"
} }
] ]
......
...@@ -8,17 +8,17 @@ ...@@ -8,17 +8,17 @@
"paintInvalidations": [ "paintInvalidations": [
{ {
"object": "LayoutSVGPath path", "object": "LayoutSVGPath path",
"rect": [202, 211, 112, 112], "rect": [189, 197, 139, 139],
"reason": "style change" "reason": "style change"
}, },
{ {
"object": "LayoutSVGPath path", "object": "LayoutSVGPath path",
"rect": [202, 211, 112, 112], "rect": [189, 197, 139, 139],
"reason": "appeared" "reason": "appeared"
}, },
{ {
"object": "LayoutSVGContainer g id='content'", "object": "LayoutSVGContainer g id='content'",
"rect": [203, 211, 111, 111], "rect": [190, 198, 137, 137],
"reason": "appeared" "reason": "appeared"
} }
] ]
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
"paintInvalidations": [ "paintInvalidations": [
{ {
"object": "LayoutSVGPath path", "object": "LayoutSVGPath path",
"rect": [202, 211, 112, 112], "rect": [189, 197, 139, 139],
"reason": "style change" "reason": "style change"
} }
] ]
......
...@@ -8,12 +8,12 @@ ...@@ -8,12 +8,12 @@
"paintInvalidations": [ "paintInvalidations": [
{ {
"object": "LayoutSVGPath path id='path'", "object": "LayoutSVGPath path id='path'",
"rect": [199, 49, 102, 52], "rect": [29, 29, 142, 92],
"reason": "subtree" "reason": "subtree"
}, },
{ {
"object": "LayoutSVGPath path id='path'", "object": "LayoutSVGPath path id='path'",
"rect": [49, 49, 102, 52], "rect": [179, 29, 122, 92],
"reason": "subtree" "reason": "subtree"
} }
] ]
......
...@@ -8,12 +8,12 @@ ...@@ -8,12 +8,12 @@
"paintInvalidations": [ "paintInvalidations": [
{ {
"object": "LayoutSVGPath polygon id='polygon'", "object": "LayoutSVGPath polygon id='polygon'",
"rect": [264, 219, 163, 106], "rect": [253, 208, 184, 129],
"reason": "full" "reason": "full"
}, },
{ {
"object": "LayoutSVGPath polygon id='polygon'", "object": "LayoutSVGPath polygon id='polygon'",
"rect": [264, 209, 163, 106], "rect": [253, 198, 184, 129],
"reason": "full" "reason": "full"
} }
] ]
......
...@@ -8,12 +8,7 @@ ...@@ -8,12 +8,7 @@
"paintInvalidations": [ "paintInvalidations": [
{ {
"object": "LayoutSVGPath polygon id='polygon'", "object": "LayoutSVGPath polygon id='polygon'",
"rect": [264, 258, 164, 67], "rect": [253, 208, 184, 129],
"reason": "full"
},
{
"object": "LayoutSVGPath polygon id='polygon'",
"rect": [264, 219, 163, 106],
"reason": "full" "reason": "full"
} }
] ]
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
"paintInvalidations": [ "paintInvalidations": [
{ {
"object": "LayoutSVGPath polygon id='polygon'", "object": "LayoutSVGPath polygon id='polygon'",
"rect": [264, 219, 163, 106], "rect": [253, 208, 184, 129],
"reason": "subtree" "reason": "subtree"
} }
] ]
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
"paintInvalidations": [ "paintInvalidations": [
{ {
"object": "LayoutSVGPath polygon id='polygon'", "object": "LayoutSVGPath polygon id='polygon'",
"rect": [264, 219, 163, 106], "rect": [253, 208, 184, 129],
"reason": "subtree" "reason": "subtree"
} }
] ]
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
"paintInvalidations": [ "paintInvalidations": [
{ {
"object": "LayoutSVGPath path", "object": "LayoutSVGPath path",
"rect": [121, 126, 68, 68], "rect": [113, 118, 84, 84],
"reason": "style change" "reason": "style change"
} }
] ]
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
"paintInvalidations": [ "paintInvalidations": [
{ {
"object": "LayoutSVGPath path", "object": "LayoutSVGPath path",
"rect": [121, 126, 68, 68], "rect": [113, 118, 84, 84],
"reason": "style change" "reason": "style change"
} }
] ]
......
...@@ -8,12 +8,12 @@ ...@@ -8,12 +8,12 @@
"paintInvalidations": [ "paintInvalidations": [
{ {
"object": "LayoutSVGPath path id='path'", "object": "LayoutSVGPath path id='path'",
"rect": [121, 126, 68, 68], "rect": [113, 118, 84, 84],
"reason": "style change" "reason": "style change"
}, },
{ {
"object": "LayoutSVGContainer g", "object": "LayoutSVGContainer g",
"rect": [122, 127, 66, 66], "rect": [114, 119, 82, 82],
"reason": "geometry" "reason": "geometry"
} }
] ]
......
...@@ -8,12 +8,12 @@ ...@@ -8,12 +8,12 @@
"paintInvalidations": [ "paintInvalidations": [
{ {
"object": "LayoutSVGPath path id='go'", "object": "LayoutSVGPath path id='go'",
"rect": [89, 94, 100, 100], "rect": [89, 94, 108, 108],
"reason": "full" "reason": "full"
}, },
{ {
"object": "LayoutSVGContainer g", "object": "LayoutSVGContainer g",
"rect": [90, 95, 98, 98], "rect": [90, 95, 106, 106],
"reason": "geometry" "reason": "geometry"
} }
] ]
......
...@@ -7,53 +7,53 @@ ...@@ -7,53 +7,53 @@
"backgroundColor": "#FFFFFF", "backgroundColor": "#FFFFFF",
"paintInvalidations": [ "paintInvalidations": [
{ {
"object": "LayoutSVGContainer use id='t2'", "object": "LayoutSVGPath polygon id='t3'",
"rect": [181, 163, 138, 137], "rect": [304, 150, 165, 164],
"reason": "style change" "reason": "style change"
}, },
{ {
"object": "LayoutSVGContainer use", "object": "LayoutSVGPath polygon",
"rect": [454, 163, 137, 137], "rect": [31, 150, 165, 164],
"reason": "SVG resource change"
},
{
"object": "LayoutSVGViewportContainer svg",
"rect": [318, 163, 137, 137],
"reason": "SVG resource change"
},
{
"object": "LayoutSVGContainer use id='t1'",
"rect": [45, 163, 137, 137],
"reason": "style change" "reason": "style change"
}, },
{ {
"object": "LayoutSVGPath polygon", "object": "LayoutSVGPath polygon",
"rect": [183, 165, 134, 134], "rect": [441, 150, 164, 164],
"reason": "style change" "reason": "style change"
}, },
{ {
"object": "LayoutSVGPath polygon", "object": "LayoutSVGPath polygon",
"rect": [456, 165, 133, 134], "rect": [168, 150, 164, 164],
"reason": "style change" "reason": "style change"
}, },
{ {
"object": "LayoutSVGPath polygon id='t3'", "object": "LayoutSVGViewportContainer svg id='poly'",
"rect": [320, 165, 133, 134], "rect": [168, 150, 164, 163],
"reason": "style change" "reason": "style change"
}, },
{ {
"object": "LayoutSVGPath polygon", "object": "LayoutSVGViewportContainer svg id='poly'",
"rect": [47, 165, 133, 134], "rect": [32, 150, 163, 163],
"reason": "style change" "reason": "style change"
}, },
{ {
"object": "LayoutSVGViewportContainer svg id='poly'", "object": "LayoutSVGContainer use id='t2'",
"rect": [47, 166, 133, 132], "rect": [181, 163, 138, 137],
"reason": "style change" "reason": "style change"
}, },
{ {
"object": "LayoutSVGViewportContainer svg id='poly'", "object": "LayoutSVGContainer use",
"rect": [184, 166, 132, 132], "rect": [454, 163, 137, 137],
"reason": "SVG resource change"
},
{
"object": "LayoutSVGViewportContainer svg",
"rect": [318, 163, 137, 137],
"reason": "SVG resource change"
},
{
"object": "LayoutSVGContainer use id='t1'",
"rect": [45, 163, 137, 137],
"reason": "style change" "reason": "style change"
} }
] ]
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
"paintInvalidations": [ "paintInvalidations": [
{ {
"object": "LayoutSVGPath path", "object": "LayoutSVGPath path",
"rect": [97, 97, 122, 122], "rect": [67, 67, 182, 182],
"reason": "full" "reason": "full"
} }
] ]
......
...@@ -7,43 +7,43 @@ ...@@ -7,43 +7,43 @@
"backgroundColor": "#FFFFFF", "backgroundColor": "#FFFFFF",
"paintInvalidations": [ "paintInvalidations": [
{ {
"object": "LayoutSVGPath polygon", "object": "LayoutSVGPath polygon id='t3'",
"rect": [183, 165, 134, 134], "rect": [304, 150, 165, 164],
"reason": "style change" "reason": "style change"
}, },
{ {
"object": "LayoutSVGPath polygon", "object": "LayoutSVGPath polygon",
"rect": [456, 165, 133, 134], "rect": [31, 150, 165, 164],
"reason": "style change" "reason": "style change"
}, },
{ {
"object": "LayoutSVGPath polygon id='t3'", "object": "LayoutSVGPath polygon",
"rect": [320, 165, 133, 134], "rect": [441, 150, 164, 164],
"reason": "style change" "reason": "style change"
}, },
{ {
"object": "LayoutSVGPath polygon", "object": "LayoutSVGPath polygon",
"rect": [47, 165, 133, 134], "rect": [168, 150, 164, 164],
"reason": "style change" "reason": "style change"
}, },
{ {
"object": "LayoutSVGContainer use id='t1'", "object": "LayoutSVGContainer use id='t2'",
"rect": [47, 166, 133, 132], "rect": [168, 150, 164, 163],
"reason": "style change" "reason": "style change"
}, },
{ {
"object": "LayoutSVGViewportContainer svg id='poly'", "object": "LayoutSVGViewportContainer svg id='poly'",
"rect": [47, 166, 133, 132], "rect": [168, 150, 164, 163],
"reason": "style change" "reason": "style change"
}, },
{ {
"object": "LayoutSVGContainer use id='t2'", "object": "LayoutSVGContainer use id='t1'",
"rect": [184, 166, 132, 132], "rect": [32, 150, 163, 163],
"reason": "style change" "reason": "style change"
}, },
{ {
"object": "LayoutSVGViewportContainer svg id='poly'", "object": "LayoutSVGViewportContainer svg id='poly'",
"rect": [184, 166, 132, 132], "rect": [32, 150, 163, 163],
"reason": "style change" "reason": "style change"
} }
] ]
......
{
"layers": [
{
"name": "LayoutView #document",
"bounds": [800, 600],
"contentsOpaque": true,
"backgroundColor": "#FFFFFF",
"paintInvalidations": [
{
"object": "LayoutSVGPath path id='path'",
"rect": [197, 197, 107, 107],
"reason": "appeared"
},
{
"object": "LayoutSVGRoot svg",
"rect": [97, 97, 106, 106],
"reason": "disappeared"
}
]
}
],
"objectPaintInvalidations": [
{
"object": "LayoutSVGPath path id='path'",
"reason": "full"
}
]
}
{
"layers": [
{
"name": "LayoutView #document",
"bounds": [800, 600],
"contentsOpaque": true,
"backgroundColor": "#FFFFFF",
"paintInvalidations": [
{
"object": "LayoutSVGPath path",
"rect": [189, 197, 139, 139],
"reason": "style change"
},
{
"object": "LayoutSVGRoot svg id='svg-root'",
"rect": [189, 197, 139, 139],
"reason": "appeared"
}
]
}
],
"objectPaintInvalidations": [
{
"object": "LayoutSVGContainer g id='content'",
"reason": "appeared"
},
{
"object": "LayoutSVGPath path",
"reason": "appeared"
},
{
"object": "LayoutSVGPath path",
"reason": "style change"
}
]
}
{
"layers": [
{
"name": "LayoutView #document",
"bounds": [800, 600],
"contentsOpaque": true,
"backgroundColor": "#FFFFFF",
"paintInvalidations": [
{
"object": "LayoutSVGPath path id='path'",
"rect": [29, 29, 142, 92],
"reason": "appeared"
},
{
"object": "LayoutSVGPath path id='path'",
"rect": [179, 29, 122, 92],
"reason": "disappeared"
}
]
}
],
"objectPaintInvalidations": [
{
"object": "LayoutSVGPath path id='path'",
"reason": "full"
}
]
}
...@@ -8,12 +8,12 @@ ...@@ -8,12 +8,12 @@
"paintInvalidations": [ "paintInvalidations": [
{ {
"object": "LayoutSVGPath polygon id='polygon'", "object": "LayoutSVGPath polygon id='polygon'",
"rect": [264, 218, 164, 107], "rect": [253, 208, 184, 129],
"reason": "full" "reason": "full"
}, },
{ {
"object": "LayoutSVGPath polygon id='polygon'", "object": "LayoutSVGPath polygon id='polygon'",
"rect": [264, 208, 164, 107], "rect": [253, 198, 184, 129],
"reason": "full" "reason": "full"
} }
] ]
......
...@@ -8,12 +8,7 @@ ...@@ -8,12 +8,7 @@
"paintInvalidations": [ "paintInvalidations": [
{ {
"object": "LayoutSVGPath polygon id='polygon'", "object": "LayoutSVGPath polygon id='polygon'",
"rect": [264, 258, 165, 67], "rect": [253, 208, 184, 129],
"reason": "full"
},
{
"object": "LayoutSVGPath polygon id='polygon'",
"rect": [264, 218, 164, 107],
"reason": "full" "reason": "full"
} }
] ]
......
{
"layers": [
{
"name": "LayoutView #document",
"bounds": [800, 600],
"contentsOpaque": true,
"backgroundColor": "#FFFFFF",
"paintInvalidations": [
{
"object": "LayoutSVGRoot svg",
"rect": [253, 208, 184, 129],
"reason": "appeared"
}
]
}
],
"objectPaintInvalidations": [
{
"object": "LayoutSVGPath polygon id='polygon'",
"reason": "full"
}
]
}
{
"layers": [
{
"name": "LayoutView #document",
"bounds": [800, 600],
"contentsOpaque": true,
"backgroundColor": "#FFFFFF",
"paintInvalidations": [
{
"object": "LayoutSVGRoot svg",
"rect": [253, 208, 184, 129],
"reason": "appeared"
}
]
}
],
"objectPaintInvalidations": [
{
"object": "LayoutSVGPath polygon id='polygon'",
"reason": "full"
}
]
}
{
"layers": [
{
"name": "LayoutView #document",
"bounds": [800, 600],
"contentsOpaque": true,
"backgroundColor": "#FFFFFF",
"paintInvalidations": [
{
"object": "LayoutSVGPath path id='path'",
"rect": [113, 118, 84, 84],
"reason": "style change"
}
]
}
],
"objectPaintInvalidations": [
{
"object": "LayoutSVGContainer g",
"reason": "geometry"
},
{
"object": "LayoutSVGPath path id='path'",
"reason": "style change"
}
]
}
{
"layers": [
{
"name": "LayoutView #document",
"bounds": [800, 600],
"contentsOpaque": true,
"backgroundColor": "#FFFFFF",
"paintInvalidations": [
{
"object": "LayoutSVGPath path id='go'",
"rect": [89, 94, 108, 108],
"reason": "full"
}
]
}
],
"objectPaintInvalidations": [
{
"object": "LayoutSVGContainer g",
"reason": "geometry"
},
{
"object": "LayoutSVGPath path id='go'",
"reason": "full"
}
]
}
{
"layers": [
{
"name": "LayoutView #document",
"bounds": [800, 600],
"contentsOpaque": true,
"backgroundColor": "#FFFFFF",
"paintInvalidations": [
{
"object": "LayoutSVGPath polygon id='t3'",
"rect": [304, 150, 165, 164],
"reason": "style change"
},
{
"object": "LayoutSVGPath polygon",
"rect": [31, 150, 165, 164],
"reason": "style change"
},
{
"object": "LayoutSVGPath polygon",
"rect": [441, 150, 164, 164],
"reason": "style change"
},
{
"object": "LayoutSVGPath polygon",
"rect": [168, 150, 164, 164],
"reason": "style change"
}
]
}
],
"objectPaintInvalidations": [
{
"object": "LayoutSVGContainer use id='t1'",
"reason": "style change"
},
{
"object": "LayoutSVGViewportContainer svg id='poly'",
"reason": "style change"
},
{
"object": "LayoutSVGPath polygon",
"reason": "style change"
},
{
"object": "LayoutSVGContainer use id='t2'",
"reason": "style change"
},
{
"object": "LayoutSVGViewportContainer svg id='poly'",
"reason": "style change"
},
{
"object": "LayoutSVGPath polygon",
"reason": "style change"
},
{
"object": "LayoutSVGPath polygon id='t3'",
"reason": "style change"
},
{
"object": "LayoutSVGPath polygon",
"reason": "style change"
}
]
}
...@@ -31,7 +31,6 @@ ...@@ -31,7 +31,6 @@
#include "core/layout/svg/SVGResources.h" #include "core/layout/svg/SVGResources.h"
#include "core/layout/svg/SVGResourcesCache.h" #include "core/layout/svg/SVGResourcesCache.h"
#include "core/svg/SVGGeometryElement.h" #include "core/svg/SVGGeometryElement.h"
#include "platform/wtf/MathExtras.h"
namespace blink { namespace blink {
...@@ -49,34 +48,9 @@ void LayoutSVGPath::UpdateShapeFromElement() { ...@@ -49,34 +48,9 @@ void LayoutSVGPath::UpdateShapeFromElement() {
} }
FloatRect LayoutSVGPath::HitTestStrokeBoundingBox() const { FloatRect LayoutSVGPath::HitTestStrokeBoundingBox() const {
const SVGComputedStyle& svg_style = Style()->SvgStyle(); if (StyleRef().SvgStyle().HasStroke())
if (svg_style.HasStroke())
return stroke_bounding_box_; return stroke_bounding_box_;
return ApproximateStrokeBoundingBox(fill_bounding_box_);
// Implementation of
// http://dev.w3.org/fxtf/css-masking-1/#compute-stroke-bounding-box
// except that we ignore whether the stroke is none.
FloatRect box = fill_bounding_box_;
const float stroke_width = this->StrokeWidth();
if (stroke_width <= 0)
return box;
float delta = stroke_width / 2;
if (svg_style.HasMiterJoinStyle()) {
const float miter = svg_style.StrokeMiterLimit();
if (miter < M_SQRT2 && svg_style.HasSquareCapStyle())
delta *= M_SQRT2;
else
delta *= miter;
} else if (svg_style.HasSquareCapStyle()) {
delta *= M_SQRT2;
}
box.Inflate(delta);
return box;
} }
FloatRect LayoutSVGPath::CalculateUpdatedStrokeBoundingBox() const { FloatRect LayoutSVGPath::CalculateUpdatedStrokeBoundingBox() const {
......
...@@ -81,15 +81,55 @@ void LayoutSVGShape::UpdateShapeFromElement() { ...@@ -81,15 +81,55 @@ void LayoutSVGShape::UpdateShapeFromElement() {
GetElement()->SetNeedsResizeObserverUpdate(); GetElement()->SetNeedsResizeObserverUpdate();
} }
namespace {
bool HasMiterJoinStyle(const SVGComputedStyle& svg_style) {
return svg_style.JoinStyle() == kMiterJoin;
}
bool HasSquareCapStyle(const SVGComputedStyle& svg_style) {
return svg_style.CapStyle() == kSquareCap;
}
} // namespace
FloatRect LayoutSVGShape::ApproximateStrokeBoundingBox(
const FloatRect& shape_bbox) const {
FloatRect stroke_box = shape_bbox;
// Implementation of
// https://drafts.fxtf.org/css-masking/#compute-stroke-bounding-box
// except that we ignore whether the stroke is none.
const float stroke_width = StrokeWidth();
if (stroke_width <= 0)
return stroke_box;
const SVGComputedStyle& svg_style = StyleRef().SvgStyle();
float delta = stroke_width / 2;
if (HasMiterJoinStyle(svg_style)) {
const float miter = svg_style.StrokeMiterLimit();
if (miter < M_SQRT2 && HasSquareCapStyle(svg_style))
delta *= M_SQRT2;
else
delta *= std::max(miter, 1.0f);
} else if (HasSquareCapStyle(svg_style)) {
delta *= M_SQRT2;
}
stroke_box.Inflate(delta);
return stroke_box;
}
FloatRect LayoutSVGShape::HitTestStrokeBoundingBox() const { FloatRect LayoutSVGShape::HitTestStrokeBoundingBox() const {
if (Style()->SvgStyle().HasStroke()) if (Style()->SvgStyle().HasStroke())
return stroke_bounding_box_; return stroke_bounding_box_;
// Implementation of // Implementation of
// http://dev.w3.org/fxtf/css-masking-1/#compute-stroke-bounding-box // https://drafts.fxtf.org/css-masking/#compute-stroke-bounding-box
// for the <rect> / <ellipse> / <circle> case except that we ignore whether // for the <rect> / <ellipse> / <circle> case except that we ignore whether
// the stroke is none. // the stroke is none.
// TODO(fs): Fold this into ApproximateStrokeBoundingBox.
FloatRect box = fill_bounding_box_; FloatRect box = fill_bounding_box_;
const float stroke_width = this->StrokeWidth(); const float stroke_width = this->StrokeWidth();
box.Inflate(stroke_width / 2); box.Inflate(stroke_width / 2);
...@@ -317,7 +357,7 @@ FloatRect LayoutSVGShape::CalculateStrokeBoundingBox() const { ...@@ -317,7 +357,7 @@ FloatRect LayoutSVGShape::CalculateStrokeBoundingBox() const {
stroke_bounding_box.Unite(stroke_bounding_rect); stroke_bounding_box.Unite(stroke_bounding_rect);
} }
} else { } else {
stroke_bounding_box.Unite(GetPath().StrokeBoundingRect(stroke_data)); stroke_bounding_box = ApproximateStrokeBoundingBox(stroke_bounding_box);
} }
} }
......
...@@ -121,6 +121,11 @@ class LayoutSVGShape : public LayoutSVGModelObject { ...@@ -121,6 +121,11 @@ class LayoutSVGShape : public LayoutSVGModelObject {
virtual bool ShapeDependentFillContains(const FloatPoint&, virtual bool ShapeDependentFillContains(const FloatPoint&,
const WindRule) const; const WindRule) const;
// Compute an approximation of the bounding box that this stroke geometry
// would generate when applied to a shape with the (tight-fitting) bounding
// box |shape_bbox|.
FloatRect ApproximateStrokeBoundingBox(const FloatRect& shape_bbox) const;
FloatRect fill_bounding_box_; FloatRect fill_bounding_box_;
FloatRect stroke_bounding_box_; FloatRect stroke_bounding_box_;
LayoutSVGShapeRareData& EnsureRareData() const; LayoutSVGShapeRareData& EnsureRareData() const;
......
...@@ -436,8 +436,6 @@ class SVGComputedStyle : public RefCounted<SVGComputedStyle> { ...@@ -436,8 +436,6 @@ class SVGComputedStyle : public RefCounted<SVGComputedStyle> {
bool HasVisibleStroke() const { bool HasVisibleStroke() const {
return HasStroke() && !StrokeWidth().IsZero(); return HasStroke() && !StrokeWidth().IsZero();
} }
bool HasSquareCapStyle() const { return CapStyle() == kSquareCap; }
bool HasMiterJoinStyle() const { return JoinStyle() == kMiterJoin; }
bool HasFill() const { return FillPaintType() != SVG_PAINTTYPE_NONE; } bool HasFill() const { return FillPaintType() != SVG_PAINTTYPE_NONE; }
protected: protected:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment