Bug 997735 - Add nsSVGUtils::FrameSpaceInCSSPxToUserSpaceOffset. r=roc

This function calculates the offset between "bounding box frame space" and "user space" for SVG frames. For non-SVG frames it returns no offset.

It's crucial that this is consistent with what nsSVGUtils::GetBBox does.

nsFilterInstance has several methods that are called by consumers before the actual painting, e.g. to calculate post filter extents or invalidation regions. Those nsFilterInstance APIs have their input and output values in "bounding box frame space" coordinates, but if the filter units are "objectBoundingBox", then those methods also do calculations involving the result of nsSVGUtils::GetBBox. So a consistent conversion is very important.
This commit is contained in:
Markus Stange 2014-04-23 11:47:42 +02:00
parent 51c046a07a
commit fc56b170d0
2 changed files with 41 additions and 0 deletions

View File

@ -889,6 +889,8 @@ nsSVGUtils::GetBBox(nsIFrame *aFrame, uint32_t aFlags)
// The spec says getBBox "Returns the tight bounding box in *current user
// space*". So we should really be doing this for all elements, but that
// needs investigation to check that we won't break too much content.
// NOTE: When changing this to apply to other frame types, make sure to
// also update nsSVGUtils::FrameSpaceInCSSPxToUserSpaceOffset.
NS_ABORT_IF_FALSE(content->IsSVG(), "bad cast");
nsSVGElement *element = static_cast<nsSVGElement*>(content);
matrix = element->PrependLocalTransformsTo(matrix,
@ -899,6 +901,35 @@ nsSVGUtils::GetBBox(nsIFrame *aFrame, uint32_t aFlags)
return nsSVGIntegrationUtils::GetSVGBBoxForNonSVGFrame(aFrame);
}
gfxPoint
nsSVGUtils::FrameSpaceInCSSPxToUserSpaceOffset(nsIFrame *aFrame)
{
if (!(aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT)) {
// The user space for non-SVG frames is defined as the bounding box of the
// frame's border-box rects over all continuations.
return gfxPoint();
}
// Leaf frames apply their own offset inside their user space.
if (aFrame->IsFrameOfType(nsIFrame::eSVGGeometry) ||
aFrame->IsSVGText()) {
return nsLayoutUtils::RectToGfxRect(aFrame->GetRect(),
nsPresContext::AppUnitsPerCSSPixel()).TopLeft();
}
// For foreignObject frames, nsSVGUtils::GetBBox applies their local
// transform, so we need to do the same here.
if (aFrame->GetType() == nsGkAtoms::svgForeignObjectFrame) {
gfxMatrix transform = static_cast<nsSVGElement*>(aFrame->GetContent())->
PrependLocalTransformsTo(gfxMatrix(),
nsSVGElement::eChildToUserSpace);
NS_ASSERTION(!transform.HasNonTranslation(), "we're relying on this being an offset-only transform");
return transform.GetTranslation();
}
return gfxPoint();
}
gfxRect
nsSVGUtils::GetRelativeRect(uint16_t aUnits, const nsSVGLength2 *aXYWH,
const gfxRect &aBBox, nsIFrame *aFrame)

View File

@ -405,6 +405,16 @@ public:
static gfxRect GetBBox(nsIFrame *aFrame,
uint32_t aFlags = eBBoxIncludeFillGeometry);
/*
* "User space" is the space that the frame's BBox (as calculated by
* nsSVGUtils::GetBBox) is in. "Frame space" is the space that has its origin
* at the top left of the union of the frame's border-box rects over all
* continuations.
* This function returns the offset one needs to add to something in frame
* space in order to get its coordinates in user space.
*/
static gfxPoint FrameSpaceInCSSPxToUserSpaceOffset(nsIFrame *aFrame);
/**
* Convert a userSpaceOnUse/objectBoundingBoxUnits rectangle that's specified
* using four nsSVGLength2 values into a user unit rectangle in user space.