Bug 1090211 - Calculate the bounds of circles and ellipses using Math when we have a rectilinear transform. r=longsonr

This commit is contained in:
Jonathan Watt 2014-10-29 01:59:36 +00:00
parent a0c5f54031
commit eb0dc8db18
5 changed files with 67 additions and 0 deletions

View File

@ -81,6 +81,34 @@ SVGCircleElement::GetLengthInfo()
//----------------------------------------------------------------------
// nsSVGPathGeometryElement methods
bool
SVGCircleElement::GetGeometryBounds(Rect* aBounds, Float aStrokeWidth,
const Matrix& aTransform)
{
float x, y, r;
GetAnimatedLengthValues(&x, &y, &r, nullptr);
if (r <= 0.f) {
// Rendering of the element is disabled
aBounds->MoveTo(x, y);
aBounds->SetEmpty();
return true;
}
if (aTransform.IsRectilinear()) {
// Optimize the case where we can treat the circle as a rectangle and
// still get tight bounds.
if (aStrokeWidth > 0.f) {
r += aStrokeWidth / 2.f;
}
Rect rect(x - r, y - r, 2 * r, 2 * r);
*aBounds = aTransform.TransformBounds(rect);
return true;
}
return false;
}
TemporaryRef<Path>
SVGCircleElement::BuildPath(PathBuilder* aBuilder)
{

View File

@ -30,6 +30,8 @@ public:
virtual bool HasValidDimensions() const MOZ_OVERRIDE;
// nsSVGPathGeometryElement methods:
virtual bool GetGeometryBounds(Rect* aBounds, Float aStrokeWidth,
const Matrix& aTransform) MOZ_OVERRIDE;
virtual TemporaryRef<Path> BuildPath(PathBuilder* aBuilder) MOZ_OVERRIDE;
virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;

View File

@ -92,6 +92,35 @@ SVGEllipseElement::GetLengthInfo()
//----------------------------------------------------------------------
// nsSVGPathGeometryElement methods
bool
SVGEllipseElement::GetGeometryBounds(Rect* aBounds, Float aStrokeWidth,
const Matrix& aTransform)
{
float x, y, rx, ry;
GetAnimatedLengthValues(&x, &y, &rx, &ry, nullptr);
if (rx <= 0.f || ry <= 0.f) {
// Rendering of the element is disabled
aBounds->MoveTo(x, y);
aBounds->SetEmpty();
return true;
}
if (aTransform.IsRectilinear()) {
// Optimize the case where we can treat the ellipse as a rectangle and
// still get tight bounds.
if (aStrokeWidth > 0.f) {
rx += aStrokeWidth / 2.f;
ry += aStrokeWidth / 2.f;
}
Rect rect(x - rx, y - ry, 2 * rx, 2 * ry);
*aBounds = aTransform.TransformBounds(rect);
return true;
}
return false;
}
TemporaryRef<Path>
SVGEllipseElement::BuildPath(PathBuilder* aBuilder)
{

View File

@ -30,6 +30,8 @@ public:
virtual bool HasValidDimensions() const MOZ_OVERRIDE;
// nsSVGPathGeometryElement methods:
virtual bool GetGeometryBounds(Rect* aBounds, Float aStrokeWidth,
const Matrix& aTransform) MOZ_OVERRIDE;
virtual TemporaryRef<Path> BuildPath(PathBuilder* aBuilder) MOZ_OVERRIDE;
virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;

View File

@ -70,6 +70,12 @@ public:
virtual bool IsMarkable();
virtual void GetMarkPoints(nsTArray<nsSVGMark> *aMarks);
/**
* A method that can be faster than using a Moz2D Path and calling GetBounds/
* GetStrokedBounds on it. It also helps us avoid rounding error for simple
* shapes and simple transforms where the Moz2D Path backends can fail to
* produce the clean integer bounds that content authors expect in some cases.
*/
virtual bool GetGeometryBounds(Rect* aBounds, Float aStrokeWidth,
const Matrix& aTransform) {
return false;