Bug 997735 - Rename nsSVGIntegrationUtils::GetOffsetToUserSpace to GetOffsetToBoundingBox. r=roc

There are three spaces that nsSVGIntegrationUtils needs to convert between. I'll call them "frame space", "bounding box frame space" and "user space".

"Bounding box frame space" has its origin at the top left of the union of a frame's border boxes over all continuations.

For SVG frames, "frame space" and "bounding box frame space" are the same because SVG frames don't have multiple continuations.

For non-SVG frames, "bounding box frame space" and "user space" are the same.

However, for SVG frames, "bounding box frame space" and "user space" are different! For example, for a <rect x="100" y="100">, the point 0,0 in frame space is at the rect's top left corner, but the point 0,0 in user space is 100,100 pixels away from the rect's corner.

nsSVGIntegrationUtils::GetOffsetToUserSpace took the non-SVG viewpoint, but it's misleading for SVG frames.
This commit is contained in:
Markus Stange 2014-04-23 11:47:31 +02:00
parent f011b43abd
commit 51c046a07a
2 changed files with 20 additions and 44 deletions

View File

@ -154,8 +154,10 @@ nsSVGIntegrationUtils::UsingEffectsForFrame(const nsIFrame* aFrame)
return (style->HasFilters() || style->mClipPath || style->mMask);
}
/* static */ nsPoint
nsSVGIntegrationUtils::GetOffsetToUserSpace(nsIFrame* aFrame)
// For non-SVG frames, this gives the offset to the frame's "user space".
// For SVG frames, this returns a zero offset.
static nsPoint
GetOffsetToBoundingBox(nsIFrame* aFrame)
{
if ((aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT)) {
// Do NOT call GetAllInFlowRectsUnion for SVG - it will get the
@ -208,7 +210,7 @@ nsSVGIntegrationUtils::GetSVGBBoxForNonSVGFrame(nsIFrame* aNonSVGFrame)
nsLayoutUtils::FirstContinuationOrIBSplitSibling(aNonSVGFrame);
// 'r' is in "user space":
nsRect r = GetPreEffectsVisualOverflowUnion(firstFrame, nullptr, nsRect(),
GetOffsetToUserSpace(firstFrame));
GetOffsetToBoundingBox(firstFrame));
return nsLayoutUtils::RectToGfxRect(r,
aNonSVGFrame->PresContext()->AppUnitsPerCSSPixel());
}
@ -217,7 +219,7 @@ nsSVGIntegrationUtils::GetSVGBBoxForNonSVGFrame(nsIFrame* aNonSVGFrame)
// continuations. When we're called for a frame with continuations, we're
// called for each continuation in turn as it's reflowed. However, it isn't
// until the last continuation is reflowed that this method's
// GetOffsetToUserSpace() and GetPreEffectsVisualOverflowUnion() calls will
// GetOffsetToBoundingBox() and GetPreEffectsVisualOverflowUnion() calls will
// obtain valid border boxes for all the continuations. As a result, we'll
// end up returning bogus post-filter visual overflow rects for all the prior
// continuations. Unfortunately, by the time the last continuation is
@ -262,7 +264,7 @@ nsRect
}
// Create an override bbox - see comment above:
nsPoint firstFrameToUserSpace = GetOffsetToUserSpace(firstFrame);
nsPoint firstFrameToBoundingBox = GetOffsetToBoundingBox(firstFrame);
// overrideBBox is in "user space", in _CSS_ pixels:
// XXX Why are we rounding out to pixel boundaries? We don't do that in
// GetSVGBBoxForNonSVGFrame, and it doesn't appear to be necessary.
@ -270,7 +272,7 @@ nsRect
nsLayoutUtils::RectToGfxRect(
GetPreEffectsVisualOverflowUnion(firstFrame, aFrame,
aPreEffectsOverflowRect,
firstFrameToUserSpace),
firstFrameToBoundingBox),
aFrame->PresContext()->AppUnitsPerCSSPixel());
overrideBBox.RoundOut();
@ -278,7 +280,7 @@ nsRect
nsFilterInstance::GetPostFilterBounds(firstFrame, &overrideBBox);
// Return overflowRect relative to aFrame, rather than "user space":
return overflowRect - (aFrame->GetOffsetTo(firstFrame) + firstFrameToUserSpace);
return overflowRect - (aFrame->GetOffsetTo(firstFrame) + firstFrameToBoundingBox);
}
nsIntRect
@ -310,18 +312,18 @@ nsSVGIntegrationUtils::AdjustInvalidAreaForSVGEffects(nsIFrame* aFrame,
return overflow.ToOutsidePixels(appUnitsPerDevPixel);
}
// Convert aInvalidRect into "user space" in app units:
nsPoint toUserSpace =
aFrame->GetOffsetTo(firstFrame) + GetOffsetToUserSpace(firstFrame);
// Convert aInvalidRect into bounding box frame space in app units:
nsPoint toBoundingBox =
aFrame->GetOffsetTo(firstFrame) + GetOffsetToBoundingBox(firstFrame);
// The initial rect was relative to the reference frame, so we need to
// remove that offset to get a rect relative to the current frame.
toUserSpace -= aToReferenceFrame;
nsRect preEffectsRect = aInvalidRect.ToAppUnits(appUnitsPerDevPixel) + toUserSpace;
toBoundingBox -= aToReferenceFrame;
nsRect preEffectsRect = aInvalidRect.ToAppUnits(appUnitsPerDevPixel) + toBoundingBox;
// Adjust the dirty area for effects, and shift it back to being relative to
// the reference frame.
nsRect result = nsFilterInstance::GetPostFilterDirtyArea(firstFrame,
preEffectsRect) - toUserSpace;
preEffectsRect) - toBoundingBox;
// Return the result, in pixels relative to the reference frame.
return result.ToOutsidePixels(appUnitsPerDevPixel);
}
@ -341,7 +343,7 @@ nsSVGIntegrationUtils::GetRequiredSourceForInvalidArea(nsIFrame* aFrame,
// Convert aDirtyRect into "user space" in app units:
nsPoint toUserSpace =
aFrame->GetOffsetTo(firstFrame) + GetOffsetToUserSpace(firstFrame);
aFrame->GetOffsetTo(firstFrame) + GetOffsetToBoundingBox(firstFrame);
nsRect postEffectsRect = aDirtyRect + toUserSpace;
// Return ther result, relative to aFrame, not in user space:
@ -357,10 +359,11 @@ nsSVGIntegrationUtils::HitTestFrameForEffects(nsIFrame* aFrame, const nsPoint& a
// Convert aPt to user space:
nsPoint toUserSpace;
if (aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT) {
// XXXmstange Isn't this wrong for svg:use and innerSVG frames?
toUserSpace = aFrame->GetPosition();
} else {
toUserSpace =
aFrame->GetOffsetTo(firstFrame) + GetOffsetToUserSpace(firstFrame);
aFrame->GetOffsetTo(firstFrame) + GetOffsetToBoundingBox(firstFrame);
}
nsPoint pt = aPt + toUserSpace;
return nsSVGUtils::HitTestClip(firstFrame, pt);
@ -460,7 +463,7 @@ nsSVGIntegrationUtils::PaintFramesWithEffects(nsRenderingContext* aCtx,
gfxContext* gfx = aCtx->ThebesContext();
gfxContextMatrixAutoSaveRestore matrixAutoSaveRestore(gfx);
nsPoint firstFrameOffset = GetOffsetToUserSpace(firstFrame);
nsPoint firstFrameOffset = GetOffsetToBoundingBox(firstFrame);
nsPoint offset = aBuilder->ToReferenceFrame(firstFrame) - firstFrameOffset;
nsPoint offsetWithoutSVGGeomFramePos;
if (firstFrame->IsFrameOfType(nsIFrame::eSVG)) {
@ -620,7 +623,7 @@ PaintFrameCallback::operator()(gfxContext* aContext,
// to have it anchored at the top left corner of the bounding box of all of
// mFrame's continuations. So we add a translation transform.
int32_t appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
nsPoint offset = nsSVGIntegrationUtils::GetOffsetToUserSpace(mFrame);
nsPoint offset = GetOffsetToBoundingBox(mFrame);
gfxPoint devPxOffset = gfxPoint(offset.x, offset.y) / appUnitsPerDevPixel;
aContext->Multiply(gfxMatrix().Translate(devPxOffset));

View File

@ -42,33 +42,6 @@ public:
static bool
UsingEffectsForFrame(const nsIFrame* aFrame);
/**
* In SVG, an element's "user space" is simply the coordinate system in place
* at the time that it is drawn. For non-SVG frames, we want any SVG effects
* to be applied to the union of the border-box rects of all of a given
* frame's continuations. This means that, when we paint a non-SVG frame with
* effects, we want to offset the effects by the distance from the frame's
* origin (the top left of its border box) to the top left of the union of
* the border-box rects of all its continuations. In other words, we need to
* apply this offset as a suplimental translation to the current coordinate
* system in order to establish the correct user space before calling into
* the SVG effects code. For the purposes of the nsSVGIntegrationUtils code
* we somewhat misappropriate the term "user space" by using it to refer
* specifically to this adjusted coordinate system.
*
* For consistency with nsIFrame::GetOffsetTo, the offset this method returns
* is the offset you need to add to a point that's relative to aFrame's
* origin (the top left of its border box) to convert it to aFrame's user
* space. In other words the value returned is actually the offset from the
* origin of aFrame's user space to aFrame.
*
* Note: This method currently only accepts a frame's first continuation
* since none of our current callers need to be able to pass in other
* continuations.
*/
static nsPoint
GetOffsetToUserSpace(nsIFrame* aFrame);
/**
* Returns the size of the union of the border-box rects of all of
* aNonSVGFrame's continuations.