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
Mouth role: AXRole: AXButton
Mouth label: smile
MouthX: 116
MouthY: 275
MouthX: 101
MouthY: 260
Text role: AXRole: AXStaticText
......
......@@ -8,12 +8,12 @@
"paintInvalidations": [
{
"object": "LayoutSVGPath path id='path'",
"rect": [198, 198, 105, 105],
"rect": [197, 197, 107, 107],
"reason": "appeared"
},
{
"object": "LayoutSVGRoot svg",
"rect": [98, 98, 104, 104],
"rect": [97, 97, 106, 106],
"reason": "disappeared"
}
]
......
......@@ -8,12 +8,12 @@
"paintInvalidations": [
{
"object": "LayoutSVGPath path",
"rect": [202, 211, 112, 112],
"rect": [189, 197, 139, 139],
"reason": "style change"
},
{
"object": "LayoutSVGRoot svg id='svg-root'",
"rect": [202, 211, 112, 112],
"rect": [189, 197, 139, 139],
"reason": "appeared"
}
]
......
......@@ -8,13 +8,13 @@
"paintInvalidations": [
{
"object": "LayoutSVGPath path id='path'",
"rect": [199, 49, 102, 52],
"reason": "disappeared"
"rect": [29, 29, 142, 92],
"reason": "appeared"
},
{
"object": "LayoutSVGPath path id='path'",
"rect": [49, 49, 102, 52],
"reason": "appeared"
"rect": [179, 29, 122, 92],
"reason": "disappeared"
}
]
}
......
......@@ -8,7 +8,7 @@
"paintInvalidations": [
{
"object": "LayoutSVGRoot svg",
"rect": [264, 218, 164, 107],
"rect": [253, 208, 184, 129],
"reason": "appeared"
}
]
......
......@@ -8,7 +8,7 @@
"paintInvalidations": [
{
"object": "LayoutSVGRoot svg",
"rect": [264, 218, 164, 107],
"rect": [253, 208, 184, 129],
"reason": "appeared"
}
]
......
......@@ -8,7 +8,7 @@
"paintInvalidations": [
{
"object": "LayoutSVGPath path id='path'",
"rect": [121, 126, 68, 68],
"rect": [113, 118, 84, 84],
"reason": "style change"
}
]
......
......@@ -8,7 +8,7 @@
"paintInvalidations": [
{
"object": "LayoutSVGPath path id='go'",
"rect": [89, 94, 100, 100],
"rect": [89, 94, 108, 108],
"reason": "full"
}
]
......
......@@ -62,108 +62,113 @@
"reason": "appeared"
},
{
"object": "LayoutSVGText text",
"rect": [615, 153, 14, 81],
"object": "LayoutSVGContainer use id='closeButtonnestedWindow'",
"rect": [374, 182, 15, 15],
"reason": "appeared"
},
{
"object": "LayoutSVGContainer use id='closeButtonnavWindow'",
"rect": [615, 83, 12, 12],
"reason": "paint property change"
},
{
"object": "LayoutSVGContainer use id='closeButtonnavWindow'",
"rect": [782, 94, 12, 11],
"object": "LayoutSVGContainer use id='minimizeButtonnavWindow'",
"rect": [754, 94, 15, 13],
"reason": "appeared"
},
{
"object": "LayoutSVGContainer use id='closeButtonnavWindow'",
"rect": [782, 94, 12, 11],
"reason": "paint property change"
},
{
"object": "LayoutSVGContainer use id='minimizeButtonnavWindow'",
"rect": [615, 115, 12, 11],
"rect": [754, 94, 15, 13],
"reason": "paint property change"
},
{
"object": "LayoutSVGContainer use id='maximizeButtonnavWindow'",
"rect": [615, 99, 12, 11],
"reason": "paint property change"
"object": "LayoutSVGContainer use id='minimizeButtonbigWindow'",
"rect": [543, 145, 15, 13],
"reason": "appeared"
},
{
"object": "LayoutSVGContainer use id='closeButtonbigWindow'",
"rect": [571, 145, 12, 11],
"object": "LayoutSVGContainer use id='minimizeButtonstatusWindow'",
"rect": [361, 345, 15, 13],
"reason": "appeared"
},
{
"object": "LayoutSVGContainer use id='minimizeButtonnestedWindow'",
"rect": [349, 184, 12, 11],
"object": "LayoutSVGContainer use id='minimizeButtoncolourPickerWindow'",
"rect": [207, 197, 15, 13],
"reason": "appeared"
},
{
"object": "LayoutSVGContainer use id='closeButtoncolourPickerWindow'",
"rect": [235, 197, 12, 11],
"object": "LayoutSVGText text",
"rect": [615, 153, 14, 81],
"reason": "appeared"
},
{
"object": "LayoutSVGContainer use id='maximizeButtonstatusWindow'",
"rect": [376, 345, 11, 12],
"object": "LayoutSVGContainer use id='closeButtonnavWindow'",
"rect": [781, 92, 14, 15],
"reason": "appeared"
},
{
"object": "LayoutSVGContainer use id='minimizeButtonstatusWindow'",
"rect": [363, 345, 11, 12],
"object": "LayoutSVGContainer use id='closeButtonnavWindow'",
"rect": [781, 92, 14, 15],
"reason": "paint property change"
},
{
"object": "LayoutSVGContainer use id='closeButtonbigWindow'",
"rect": [570, 143, 14, 15],
"reason": "appeared"
},
{
"object": "LayoutSVGContainer use id='maximizeButtonnavWindow'",
"rect": [769, 94, 11, 11],
"object": "LayoutSVGContainer use id='closeButtoncolourPickerWindow'",
"rect": [234, 195, 14, 15],
"reason": "appeared"
},
{
"object": "LayoutSVGContainer use id='maximizeButtonnavWindow'",
"rect": [769, 94, 11, 11],
"object": "LayoutSVGContainer use id='closeButtonnavWindow'",
"rect": [614, 82, 14, 14],
"reason": "paint property change"
},
{
"object": "LayoutSVGContainer use id='minimizeButtonnavWindow'",
"rect": [756, 94, 11, 11],
"object": "LayoutSVGContainer use id='closeButtonsmallWindow'",
"rect": [453, 378, 14, 14],
"reason": "appeared"
},
{
"object": "LayoutSVGContainer use id='minimizeButtonnavWindow'",
"rect": [756, 94, 11, 11],
"rect": [614, 115, 14, 13],
"reason": "paint property change"
},
{
"object": "LayoutSVGContainer use id='maximizeButtonbigWindow'",
"rect": [558, 145, 11, 11],
"object": "LayoutSVGContainer use id='minimizeButtonsmallWindow'",
"rect": [426, 379, 14, 13],
"reason": "appeared"
},
{
"object": "LayoutSVGContainer use id='minimizeButtonbigWindow'",
"rect": [545, 145, 11, 11],
"object": "LayoutSVGContainer use id='minimizeButtonnestedWindow'",
"rect": [348, 184, 14, 13],
"reason": "appeared"
},
{
"object": "LayoutSVGContainer use id='closeButtonsmallWindow'",
"rect": [454, 379, 11, 11],
"object": "LayoutSVGContainer use id='maximizeButtonnavWindow'",
"rect": [615, 99, 12, 11],
"reason": "paint property change"
},
{
"object": "LayoutSVGContainer use id='maximizeButtonstatusWindow'",
"rect": [376, 345, 11, 12],
"reason": "appeared"
},
{
"object": "LayoutSVGContainer use id='maximizeButtonsmallWindow'",
"rect": [441, 379, 11, 11],
"object": "LayoutSVGContainer use id='maximizeButtonnavWindow'",
"rect": [769, 94, 11, 11],
"reason": "appeared"
},
{
"object": "LayoutSVGContainer use id='minimizeButtonsmallWindow'",
"rect": [428, 379, 11, 11],
"object": "LayoutSVGContainer use id='maximizeButtonnavWindow'",
"rect": [769, 94, 11, 11],
"reason": "paint property change"
},
{
"object": "LayoutSVGContainer use id='maximizeButtonbigWindow'",
"rect": [558, 145, 11, 11],
"reason": "appeared"
},
{
"object": "LayoutSVGContainer use id='closeButtonnestedWindow'",
"rect": [376, 184, 11, 11],
"object": "LayoutSVGContainer use id='maximizeButtonsmallWindow'",
"rect": [441, 379, 11, 11],
"reason": "appeared"
},
{
......@@ -175,11 +180,6 @@
"object": "LayoutSVGContainer use id='maximizeButtoncolourPickerWindow'",
"rect": [222, 197, 11, 11],
"reason": "appeared"
},
{
"object": "LayoutSVGContainer use id='minimizeButtoncolourPickerWindow'",
"rect": [209, 197, 11, 11],
"reason": "appeared"
}
]
}
......
......@@ -8,12 +8,12 @@
"paintInvalidations": [
{
"object": "LayoutSVGPath path id='path'",
"rect": [98, 98, 104, 104],
"rect": [197, 197, 107, 107],
"reason": "subtree"
},
{
"object": "LayoutSVGPath path id='path'",
"rect": [199, 199, 103, 103],
"rect": [97, 97, 106, 106],
"reason": "subtree"
}
]
......
......@@ -8,17 +8,17 @@
"paintInvalidations": [
{
"object": "LayoutSVGPath path",
"rect": [202, 211, 112, 112],
"rect": [189, 197, 139, 139],
"reason": "style change"
},
{
"object": "LayoutSVGPath path",
"rect": [202, 211, 112, 112],
"rect": [189, 197, 139, 139],
"reason": "appeared"
},
{
"object": "LayoutSVGContainer g id='content'",
"rect": [203, 211, 111, 111],
"rect": [190, 198, 137, 137],
"reason": "appeared"
}
]
......
......@@ -8,7 +8,7 @@
"paintInvalidations": [
{
"object": "LayoutSVGPath path",
"rect": [202, 211, 112, 112],
"rect": [189, 197, 139, 139],
"reason": "style change"
}
]
......
......@@ -8,12 +8,12 @@
"paintInvalidations": [
{
"object": "LayoutSVGPath path id='path'",
"rect": [199, 49, 102, 52],
"rect": [29, 29, 142, 92],
"reason": "subtree"
},
{
"object": "LayoutSVGPath path id='path'",
"rect": [49, 49, 102, 52],
"rect": [179, 29, 122, 92],
"reason": "subtree"
}
]
......
......@@ -8,12 +8,12 @@
"paintInvalidations": [
{
"object": "LayoutSVGPath polygon id='polygon'",
"rect": [264, 219, 163, 106],
"rect": [253, 208, 184, 129],
"reason": "full"
},
{
"object": "LayoutSVGPath polygon id='polygon'",
"rect": [264, 209, 163, 106],
"rect": [253, 198, 184, 129],
"reason": "full"
}
]
......
......@@ -8,12 +8,7 @@
"paintInvalidations": [
{
"object": "LayoutSVGPath polygon id='polygon'",
"rect": [264, 258, 164, 67],
"reason": "full"
},
{
"object": "LayoutSVGPath polygon id='polygon'",
"rect": [264, 219, 163, 106],
"rect": [253, 208, 184, 129],
"reason": "full"
}
]
......
......@@ -8,7 +8,7 @@
"paintInvalidations": [
{
"object": "LayoutSVGPath polygon id='polygon'",
"rect": [264, 219, 163, 106],
"rect": [253, 208, 184, 129],
"reason": "subtree"
}
]
......
......@@ -8,7 +8,7 @@
"paintInvalidations": [
{
"object": "LayoutSVGPath polygon id='polygon'",
"rect": [264, 219, 163, 106],
"rect": [253, 208, 184, 129],
"reason": "subtree"
}
]
......
......@@ -8,7 +8,7 @@
"paintInvalidations": [
{
"object": "LayoutSVGPath path",
"rect": [121, 126, 68, 68],
"rect": [113, 118, 84, 84],
"reason": "style change"
}
]
......
......@@ -8,7 +8,7 @@
"paintInvalidations": [
{
"object": "LayoutSVGPath path",
"rect": [121, 126, 68, 68],
"rect": [113, 118, 84, 84],
"reason": "style change"
}
]
......
......@@ -8,12 +8,12 @@
"paintInvalidations": [
{
"object": "LayoutSVGPath path id='path'",
"rect": [121, 126, 68, 68],
"rect": [113, 118, 84, 84],
"reason": "style change"
},
{
"object": "LayoutSVGContainer g",
"rect": [122, 127, 66, 66],
"rect": [114, 119, 82, 82],
"reason": "geometry"
}
]
......
......@@ -8,12 +8,12 @@
"paintInvalidations": [
{
"object": "LayoutSVGPath path id='go'",
"rect": [89, 94, 100, 100],
"rect": [89, 94, 108, 108],
"reason": "full"
},
{
"object": "LayoutSVGContainer g",
"rect": [90, 95, 98, 98],
"rect": [90, 95, 106, 106],
"reason": "geometry"
}
]
......
......@@ -7,53 +7,53 @@
"backgroundColor": "#FFFFFF",
"paintInvalidations": [
{
"object": "LayoutSVGContainer use id='t2'",
"rect": [181, 163, 138, 137],
"object": "LayoutSVGPath polygon id='t3'",
"rect": [304, 150, 165, 164],
"reason": "style change"
},
{
"object": "LayoutSVGContainer use",
"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],
"object": "LayoutSVGPath polygon",
"rect": [31, 150, 165, 164],
"reason": "style change"
},
{
"object": "LayoutSVGPath polygon",
"rect": [183, 165, 134, 134],
"rect": [441, 150, 164, 164],
"reason": "style change"
},
{
"object": "LayoutSVGPath polygon",
"rect": [456, 165, 133, 134],
"rect": [168, 150, 164, 164],
"reason": "style change"
},
{
"object": "LayoutSVGPath polygon id='t3'",
"rect": [320, 165, 133, 134],
"object": "LayoutSVGViewportContainer svg id='poly'",
"rect": [168, 150, 164, 163],
"reason": "style change"
},
{
"object": "LayoutSVGPath polygon",
"rect": [47, 165, 133, 134],
"object": "LayoutSVGViewportContainer svg id='poly'",
"rect": [32, 150, 163, 163],
"reason": "style change"
},
{
"object": "LayoutSVGViewportContainer svg id='poly'",
"rect": [47, 166, 133, 132],
"object": "LayoutSVGContainer use id='t2'",
"rect": [181, 163, 138, 137],
"reason": "style change"
},
{
"object": "LayoutSVGViewportContainer svg id='poly'",
"rect": [184, 166, 132, 132],
"object": "LayoutSVGContainer use",
"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"
}
]
......
......@@ -8,7 +8,7 @@
"paintInvalidations": [
{
"object": "LayoutSVGPath path",
"rect": [97, 97, 122, 122],
"rect": [67, 67, 182, 182],
"reason": "full"
}
]
......
......@@ -7,43 +7,43 @@
"backgroundColor": "#FFFFFF",
"paintInvalidations": [
{
"object": "LayoutSVGPath polygon",
"rect": [183, 165, 134, 134],
"object": "LayoutSVGPath polygon id='t3'",
"rect": [304, 150, 165, 164],
"reason": "style change"
},
{
"object": "LayoutSVGPath polygon",
"rect": [456, 165, 133, 134],
"rect": [31, 150, 165, 164],
"reason": "style change"
},
{
"object": "LayoutSVGPath polygon id='t3'",
"rect": [320, 165, 133, 134],
"object": "LayoutSVGPath polygon",
"rect": [441, 150, 164, 164],
"reason": "style change"
},
{
"object": "LayoutSVGPath polygon",
"rect": [47, 165, 133, 134],
"rect": [168, 150, 164, 164],
"reason": "style change"
},
{
"object": "LayoutSVGContainer use id='t1'",
"rect": [47, 166, 133, 132],
"object": "LayoutSVGContainer use id='t2'",
"rect": [168, 150, 164, 163],
"reason": "style change"
},
{
"object": "LayoutSVGViewportContainer svg id='poly'",
"rect": [47, 166, 133, 132],
"rect": [168, 150, 164, 163],
"reason": "style change"
},
{
"object": "LayoutSVGContainer use id='t2'",
"rect": [184, 166, 132, 132],
"object": "LayoutSVGContainer use id='t1'",
"rect": [32, 150, 163, 163],
"reason": "style change"
},
{
"object": "LayoutSVGViewportContainer svg id='poly'",
"rect": [184, 166, 132, 132],
"rect": [32, 150, 163, 163],
"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 @@
"paintInvalidations": [
{
"object": "LayoutSVGPath polygon id='polygon'",
"rect": [264, 218, 164, 107],
"rect": [253, 208, 184, 129],
"reason": "full"
},
{
"object": "LayoutSVGPath polygon id='polygon'",
"rect": [264, 208, 164, 107],
"rect": [253, 198, 184, 129],
"reason": "full"
}
]
......
......@@ -8,12 +8,7 @@
"paintInvalidations": [
{
"object": "LayoutSVGPath polygon id='polygon'",
"rect": [264, 258, 165, 67],
"reason": "full"
},
{
"object": "LayoutSVGPath polygon id='polygon'",
"rect": [264, 218, 164, 107],
"rect": [253, 208, 184, 129],
"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 @@
#include "core/layout/svg/SVGResources.h"
#include "core/layout/svg/SVGResourcesCache.h"
#include "core/svg/SVGGeometryElement.h"
#include "platform/wtf/MathExtras.h"
namespace blink {
......@@ -49,34 +48,9 @@ void LayoutSVGPath::UpdateShapeFromElement() {
}
FloatRect LayoutSVGPath::HitTestStrokeBoundingBox() const {
const SVGComputedStyle& svg_style = Style()->SvgStyle();
if (svg_style.HasStroke())
if (StyleRef().SvgStyle().HasStroke())
return stroke_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;
return ApproximateStrokeBoundingBox(fill_bounding_box_);
}
FloatRect LayoutSVGPath::CalculateUpdatedStrokeBoundingBox() const {
......
......@@ -81,15 +81,55 @@ void LayoutSVGShape::UpdateShapeFromElement() {
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 {
if (Style()->SvgStyle().HasStroke())
return stroke_bounding_box_;
// 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
// the stroke is none.
// TODO(fs): Fold this into ApproximateStrokeBoundingBox.
FloatRect box = fill_bounding_box_;
const float stroke_width = this->StrokeWidth();
box.Inflate(stroke_width / 2);
......@@ -317,7 +357,7 @@ FloatRect LayoutSVGShape::CalculateStrokeBoundingBox() const {
stroke_bounding_box.Unite(stroke_bounding_rect);
}
} else {
stroke_bounding_box.Unite(GetPath().StrokeBoundingRect(stroke_data));
stroke_bounding_box = ApproximateStrokeBoundingBox(stroke_bounding_box);
}
}
......
......@@ -121,6 +121,11 @@ class LayoutSVGShape : public LayoutSVGModelObject {
virtual bool ShapeDependentFillContains(const FloatPoint&,
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 stroke_bounding_box_;
LayoutSVGShapeRareData& EnsureRareData() const;
......
......@@ -436,8 +436,6 @@ class SVGComputedStyle : public RefCounted<SVGComputedStyle> {
bool HasVisibleStroke() const {
return HasStroke() && !StrokeWidth().IsZero();
}
bool HasSquareCapStyle() const { return CapStyle() == kSquareCap; }
bool HasMiterJoinStyle() const { return JoinStyle() == kMiterJoin; }
bool HasFill() const { return FillPaintType() != SVG_PAINTTYPE_NONE; }
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