Bug 1090934 - Get bounds of line element using maths. r=jwatt

This commit is contained in:
Robert Longson 2015-01-22 09:36:08 +00:00
parent ce0419c259
commit d76cf3c625
14 changed files with 85 additions and 13 deletions

View File

@ -83,7 +83,7 @@ SVGCircleElement::GetLengthInfo()
bool
SVGCircleElement::GetGeometryBounds(Rect* aBounds, Float aStrokeWidth,
const Matrix& aTransform)
CapStyle aCapStyle, const Matrix& aTransform)
{
float x, y, r;
GetAnimatedLengthValues(&x, &y, &r, nullptr);

View File

@ -31,7 +31,7 @@ public:
// nsSVGPathGeometryElement methods:
virtual bool GetGeometryBounds(Rect* aBounds, Float aStrokeWidth,
const Matrix& aTransform) MOZ_OVERRIDE;
CapStyle aCapStyle, 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

@ -94,7 +94,7 @@ SVGEllipseElement::GetLengthInfo()
bool
SVGEllipseElement::GetGeometryBounds(Rect* aBounds, Float aStrokeWidth,
const Matrix& aTransform)
CapStyle aCapStyle, const Matrix& aTransform)
{
float x, y, rx, ry;
GetAnimatedLengthValues(&x, &y, &rx, &ry, nullptr);

View File

@ -31,7 +31,7 @@ public:
// nsSVGPathGeometryElement methods:
virtual bool GetGeometryBounds(Rect* aBounds, Float aStrokeWidth,
const Matrix& aTransform) MOZ_OVERRIDE;
CapStyle aCapStyle, 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

@ -228,7 +228,7 @@ SVGImageElement::IsAttributeMapped(const nsIAtom* name) const
be a rectangle. */
bool
SVGImageElement::GetGeometryBounds(Rect* aBounds, Float aStrokeWidth,
const Matrix& aTransform)
CapStyle aCapStyle, const Matrix& aTransform)
{
Rect rect;
GetAnimatedLengthValues(&rect.x, &rect.y, &rect.width,

View File

@ -54,7 +54,7 @@ public:
// nsSVGPathGeometryElement methods:
virtual bool GetGeometryBounds(Rect* aBounds, Float aStrokeWidth,
const Matrix& aTransform) MOZ_OVERRIDE;
CapStyle cap, const Matrix& aTransform) MOZ_OVERRIDE;
virtual TemporaryRef<Path> BuildPath(PathBuilder* aBuilder) MOZ_OVERRIDE;
// nsSVGSVGElement methods:

View File

@ -126,5 +126,66 @@ SVGLineElement::BuildPath(PathBuilder* aBuilder)
return aBuilder->Finish();
}
bool
SVGLineElement::GetGeometryBounds(Rect* aBounds, Float aStrokeWidth,
CapStyle aCapStyle, const Matrix& aTransform)
{
float x1, y1, x2, y2;
GetAnimatedLengthValues(&x1, &y1, &x2, &y2, nullptr);
if (aStrokeWidth <= 0) {
*aBounds = Rect(aTransform * Point(x1, y1), Size());
aBounds->ExpandToEnclose(aTransform * Point(x2, y2));
return true;
}
if (aCapStyle == CapStyle::ROUND) {
if (!aTransform.IsRectilinear()) {
// TODO: handle this case.
return false;
}
Rect bounds(Point(x1, y1), Size());
bounds.ExpandToEnclose(Point(x2, y2));
bounds.Inflate(aStrokeWidth / 2.f);
*aBounds = aTransform.TransformBounds(bounds);
return true;
}
Float length = Float(NS_hypot(x2 - x1, y2 - y1));
Float xDelta;
Float yDelta;
if (aCapStyle == CapStyle::BUTT) {
if (length == 0.f) {
xDelta = yDelta = 0.f;
} else {
Float ratio = aStrokeWidth / 2.f / length;
xDelta = ratio * (y2 - y1);
yDelta = ratio * (x2 - x1);
}
} else {
MOZ_ASSERT(aCapStyle == CapStyle::SQUARE);
if (length == 0.f) {
xDelta = yDelta = aStrokeWidth / 2.f;
} else {
Float ratio = aStrokeWidth / 2.f / length;
xDelta = yDelta = ratio * (fabs(y2 - y1) + fabs(x2 - x1));
}
}
Point points[4];
points[0] = Point(x1 - xDelta, y1 - yDelta);
points[1] = Point(x1 + xDelta, y1 + yDelta);
points[2] = Point(x2 + xDelta, y2 + yDelta);
points[3] = Point(x2 - xDelta, y2 - yDelta);
*aBounds = Rect(aTransform * points[0], Size());
for (uint32_t i = 1; i < 4; ++i) {
aBounds->ExpandToEnclose(aTransform * points[i]);
}
return true;
}
} // namespace dom
} // namespace mozilla

View File

@ -34,6 +34,8 @@ public:
virtual void GetMarkPoints(nsTArray<nsSVGMark> *aMarks) MOZ_OVERRIDE;
virtual void GetAsSimplePath(SimplePath* aSimplePath) MOZ_OVERRIDE;
virtual TemporaryRef<Path> BuildPath(PathBuilder* aBuilder) MOZ_OVERRIDE;
virtual bool GetGeometryBounds(Rect* aBounds, Float aStrokeWidth,
CapStyle cap, const Matrix& aTransform) MOZ_OVERRIDE;
virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;

View File

@ -112,7 +112,7 @@ SVGRectElement::GetLengthInfo()
bool
SVGRectElement::GetGeometryBounds(Rect* aBounds, Float aStrokeWidth,
const Matrix& aTransform)
CapStyle aCapStyle, const Matrix& aTransform)
{
Rect rect;
Float rx, ry;

View File

@ -31,7 +31,7 @@ public:
// nsSVGPathGeometryElement methods:
virtual bool GetGeometryBounds(Rect* aBounds, Float aStrokeWidth,
const Matrix& aTransform) MOZ_OVERRIDE;
CapStyle aCapStyle, const Matrix& aTransform) MOZ_OVERRIDE;
virtual void GetAsSimplePath(SimplePath* aSimplePath) MOZ_OVERRIDE;
virtual TemporaryRef<Path> BuildPath(PathBuilder* aBuilder = nullptr) MOZ_OVERRIDE;

View File

@ -31,6 +31,7 @@ typedef mozilla::dom::SVGGraphicsElement nsSVGPathGeometryElementBase;
class nsSVGPathGeometryElement : public nsSVGPathGeometryElementBase
{
protected:
typedef mozilla::gfx::CapStyle CapStyle;
typedef mozilla::gfx::DrawTarget DrawTarget;
typedef mozilla::gfx::FillRule FillRule;
typedef mozilla::gfx::Float Float;
@ -77,7 +78,7 @@ public:
* produce the clean integer bounds that content authors expect in some cases.
*/
virtual bool GetGeometryBounds(Rect* aBounds, Float aStrokeWidth,
const Matrix& aTransform) {
CapStyle aCapStyle, const Matrix& aTransform) {
return false;
}

View File

@ -122,7 +122,7 @@ nsSVGPolyElement::GetMarkPoints(nsTArray<nsSVGMark> *aMarks)
bool
nsSVGPolyElement::GetGeometryBounds(Rect* aBounds, Float aStrokeWidth,
const Matrix& aTransform)
CapStyle aCapStyle, const Matrix& aTransform)
{
const SVGPointList &points = mPoints.GetAnimValue();

View File

@ -46,7 +46,7 @@ public:
virtual bool IsMarkable() MOZ_OVERRIDE { return true; }
virtual void GetMarkPoints(nsTArray<nsSVGMark> *aMarks) MOZ_OVERRIDE;
virtual bool GetGeometryBounds(Rect* aBounds, Float aStrokeWidth,
const Matrix& aTransform) MOZ_OVERRIDE;
CapStyle aCapStyle, const Matrix& aTransform) MOZ_OVERRIDE;
// WebIDL
already_AddRefed<mozilla::DOMSVGPointList> Points();

View File

@ -471,9 +471,17 @@ nsSVGPathGeometryFrame::GetBBoxContribution(const Matrix &aToBBoxUserspace,
bool gotSimpleBounds = false;
if (!StyleSVGReset()->HasNonScalingStroke()) {
Float strokeWidth = getStroke ? nsSVGUtils::GetStrokeWidth(this) : 0.f;
SVGContentUtils::AutoStrokeOptions strokeOptions;
strokeOptions.mLineWidth = 0.f;
if (getStroke) {
SVGContentUtils::GetStrokeOptions(&strokeOptions, element,
StyleContext(), nullptr,
SVGContentUtils::eIgnoreStrokeDashing);
}
Rect simpleBounds;
gotSimpleBounds = element->GetGeometryBounds(&simpleBounds, strokeWidth,
gotSimpleBounds = element->GetGeometryBounds(&simpleBounds,
strokeOptions.mLineWidth,
strokeOptions.mLineCap,
aToBBoxUserspace);
if (gotSimpleBounds) {
bbox = simpleBounds;