Bug 934156 - Make the SVG elements' BuildPath methods return nullptr when the element is disabled. r=dholbert

This commit is contained in:
Jonathan Watt 2013-11-06 10:05:18 +00:00
parent 509059ce0b
commit bfc390bc61
6 changed files with 64 additions and 54 deletions

View File

@ -96,15 +96,17 @@ SVGCircleElement::ConstructPath(gfxContext *aCtx)
TemporaryRef<Path>
SVGCircleElement::BuildPath()
{
RefPtr<PathBuilder> pathBuilder = CreatePathBuilder();
float x, y, r;
GetAnimatedLengthValues(&x, &y, &r, nullptr);
if (r > 0.0f) {
pathBuilder->Arc(Point(x, y), r, 0, Float(2*M_PI));
if (r <= 0.0f) {
return nullptr;
}
RefPtr<PathBuilder> pathBuilder = CreatePathBuilder();
pathBuilder->Arc(Point(x, y), r, 0, Float(2*M_PI));
return pathBuilder->Finish();
}

View File

@ -107,15 +107,17 @@ SVGEllipseElement::ConstructPath(gfxContext *aCtx)
TemporaryRef<Path>
SVGEllipseElement::BuildPath()
{
RefPtr<PathBuilder> pathBuilder = CreatePathBuilder();
float x, y, rx, ry;
GetAnimatedLengthValues(&x, &y, &rx, &ry, nullptr);
if (rx > 0.0f && ry > 0.0f) {
AppendEllipseToPath(pathBuilder, Point(x, y), Size(2.0*rx, 2.0*ry));
if (rx <= 0.0f || ry <= 0.0f) {
return nullptr;
}
RefPtr<PathBuilder> pathBuilder = CreatePathBuilder();
AppendEllipseToPath(pathBuilder, Point(x, y), Size(2.0*rx, 2.0*ry));
return pathBuilder->Finish();
}

View File

@ -245,20 +245,22 @@ SVGImageElement::BuildPath()
// We get called in order to get bounds for this element, and for
// hit-testing against it. For that we just pretend to be a rectangle.
RefPtr<PathBuilder> pathBuilder = CreatePathBuilder();
float x, y, width, height;
GetAnimatedLengthValues(&x, &y, &width, &height, nullptr);
if (width <= 0 || height <= 0) {
Rect r(x, y, width, height);
pathBuilder->MoveTo(r.TopLeft());
pathBuilder->LineTo(r.TopRight());
pathBuilder->LineTo(r.BottomRight());
pathBuilder->LineTo(r.BottomLeft());
pathBuilder->Close();
return nullptr;
}
RefPtr<PathBuilder> pathBuilder = CreatePathBuilder();
Rect r(x, y, width, height);
pathBuilder->MoveTo(r.TopLeft());
pathBuilder->LineTo(r.TopRight());
pathBuilder->LineTo(r.BottomRight());
pathBuilder->LineTo(r.BottomLeft());
pathBuilder->Close();
return pathBuilder->Finish();
}

View File

@ -155,44 +155,46 @@ SVGRectElement::ConstructPath(gfxContext *aCtx)
TemporaryRef<Path>
SVGRectElement::BuildPath()
{
RefPtr<PathBuilder> pathBuilder = CreatePathBuilder();
float x, y, width, height, rx, ry;
GetAnimatedLengthValues(&x, &y, &width, &height, &rx, &ry, nullptr);
if (width > 0 && height > 0) {
rx = std::max(rx, 0.0f);
ry = std::max(ry, 0.0f);
if (width <= 0 || height <= 0) {
return nullptr;
}
if (rx == 0 && ry == 0) {
// Optimization for the no rounded corners case.
Rect r(x, y, width, height);
pathBuilder->MoveTo(r.TopLeft());
pathBuilder->LineTo(r.TopRight());
pathBuilder->LineTo(r.BottomRight());
pathBuilder->LineTo(r.BottomLeft());
pathBuilder->Close();
} else {
// If either the 'rx' or the 'ry' attribute isn't set, then we have to
// set it to the value of the other:
bool hasRx = mLengthAttributes[ATTR_RX].IsExplicitlySet();
bool hasRy = mLengthAttributes[ATTR_RY].IsExplicitlySet();
MOZ_ASSERT(hasRx || hasRy);
RefPtr<PathBuilder> pathBuilder = CreatePathBuilder();
if (hasRx && !hasRy) {
ry = rx;
} else if (hasRy && !hasRx) {
rx = ry;
}
rx = std::max(rx, 0.0f);
ry = std::max(ry, 0.0f);
// Clamp rx and ry to half the rect's width and height respectively:
rx = std::min(rx, width / 2);
ry = std::min(ry, height / 2);
if (rx == 0 && ry == 0) {
// Optimization for the no rounded corners case.
Rect r(x, y, width, height);
pathBuilder->MoveTo(r.TopLeft());
pathBuilder->LineTo(r.TopRight());
pathBuilder->LineTo(r.BottomRight());
pathBuilder->LineTo(r.BottomLeft());
pathBuilder->Close();
} else {
// If either the 'rx' or the 'ry' attribute isn't set, then we have to
// set it to the value of the other:
bool hasRx = mLengthAttributes[ATTR_RX].IsExplicitlySet();
bool hasRy = mLengthAttributes[ATTR_RY].IsExplicitlySet();
MOZ_ASSERT(hasRx || hasRy);
Size cornerRadii(rx, ry);
Size radii[] = { cornerRadii, cornerRadii, cornerRadii, cornerRadii };
AppendRoundedRectToPath(pathBuilder, Rect(x, y, width, height), radii);
if (hasRx && !hasRy) {
ry = rx;
} else if (hasRy && !hasRx) {
rx = ry;
}
// Clamp rx and ry to half the rect's width and height respectively:
rx = std::min(rx, width / 2);
ry = std::min(ry, height / 2);
Size cornerRadii(rx, ry);
Size radii[] = { cornerRadii, cornerRadii, cornerRadii, cornerRadii };
AppendRoundedRectToPath(pathBuilder, Rect(x, y, width, height), radii);
}
return pathBuilder->Finish();

View File

@ -62,7 +62,7 @@ public:
/**
* Returns a Path that can be used to paint, hit-test or calculate bounds for
* this element.
* this element. May return nullptr if there is no [valid] path.
*/
virtual mozilla::TemporaryRef<Path> BuildPath() = 0;

View File

@ -125,15 +125,17 @@ nsSVGPolyElement::ConstructPath(gfxContext *aCtx)
TemporaryRef<Path>
nsSVGPolyElement::BuildPath()
{
RefPtr<PathBuilder> pathBuilder = CreatePathBuilder();
const SVGPointList &points = mPoints.GetAnimValue();
if (!points.IsEmpty()) {
pathBuilder->MoveTo(points[0]);
for (uint32_t i = 1; i < points.Length(); ++i) {
pathBuilder->LineTo(points[i]);
}
if (points.IsEmpty()) {
return nullptr;
}
RefPtr<PathBuilder> pathBuilder = CreatePathBuilder();
pathBuilder->MoveTo(points[0]);
for (uint32_t i = 1; i < points.Length(); ++i) {
pathBuilder->LineTo(points[i]);
}
return pathBuilder->Finish();