Commit 8f4c8e6d authored by fmalita's avatar fmalita Committed by Commit bot

Compute exact bounds for SVGPathElement::getBBox()

The current implementation relies on SkPath::getBounds(), which
computes a conservative result (includes control points).

Use SkPathOps::TightBounds() instead, for an exact answer.

BUG=230599
R=fs@opera.com,pdr@chromium.org,schenney@chromium.org,caryclark@google.com

Review-Url: https://codereview.chromium.org/2168133002
Cr-Commit-Position: refs/heads/master@{#407268}
parent 4d8e12df
......@@ -207,4 +207,12 @@ void SVGPathElement::removedFrom(ContainerNode* rootParent)
invalidateMPathDependencies();
}
FloatRect SVGPathElement::getBBox()
{
document().updateStyleAndLayoutIgnorePendingStylesheets();
// We want the exact bounds.
return SVGPathElement::asPath().boundingRect(Path::BoundsType::Exact);
}
} // namespace blink
......@@ -50,6 +50,8 @@ public:
bool isPresentationAttribute(const QualifiedName&) const override;
bool isPresentationAttributeWithSVGDOM(const QualifiedName&) const override;
FloatRect getBBox() override;
DECLARE_VIRTUAL_TRACE();
private:
......
......@@ -115,14 +115,31 @@ bool Path::strokeContains(const FloatPoint& point, const StrokeData& strokeData)
return strokePath(strokeData).contains(WebCoreFloatToSkScalar(point.x()), WebCoreFloatToSkScalar(point.y()));
}
FloatRect Path::boundingRect() const
namespace {
FloatRect pathBounds(const SkPath& path, Path::BoundsType boundsType)
{
SkRect bounds;
if (boundsType == Path::BoundsType::Conservative
|| !TightBounds(path, &bounds)
|| bounds.isEmpty()) // workaround for https://bugs.chromium.org/p/skia/issues/detail?id=5555
return path.getBounds();
DCHECK_EQ(boundsType, Path::BoundsType::Exact);
return bounds;
}
} // anonymous ns
// TODO(fmalita): evaluate returning exact bounds in all cases.
FloatRect Path::boundingRect(BoundsType boundsType) const
{
return m_path.getBounds();
return pathBounds(m_path, boundsType);
}
FloatRect Path::strokeBoundingRect(const StrokeData& strokeData) const
FloatRect Path::strokeBoundingRect(const StrokeData& strokeData, BoundsType boundsType) const
{
return strokePath(strokeData).getBounds();
return pathBounds(strokePath(strokeData), boundsType);
}
static FloatPoint* convertPathPoints(FloatPoint dst[], const SkPoint src[], int count)
......
......@@ -78,8 +78,13 @@ public:
bool contains(const FloatPoint&) const;
bool contains(const FloatPoint&, WindRule) const;
bool strokeContains(const FloatPoint&, const StrokeData&) const;
FloatRect boundingRect() const;
FloatRect strokeBoundingRect(const StrokeData&) const;
enum class BoundsType {
Conservative, // Fast version, includes control points.
Exact, // Tight, slower version.
};
FloatRect boundingRect(BoundsType = BoundsType::Conservative) const;
FloatRect strokeBoundingRect(const StrokeData&, BoundsType = BoundsType::Conservative) const;
float length() const;
FloatPoint pointAtLength(float length) const;
......
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