mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 20:05:49 +00:00
Bug 1090934 - Get bounds of line element using maths. r=jwatt
This commit is contained in:
parent
0db90d7550
commit
176139eb4c
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user