Bug 765505 - Clean up filter code. r=longsonr.

This commit is contained in:
Jonathan Watt 2012-06-16 21:23:48 +01:00
parent 1011a23af6
commit 5691b0a166
7 changed files with 130 additions and 113 deletions

View File

@ -3306,10 +3306,10 @@ nsSVGFETurbulenceElement::Filter(nsSVGFilterInstance *instance,
InitSeed((PRInt32)seed);
// XXXroc this makes absolutely no sense to me.
float filterX = instance->GetFilterRect().X();
float filterY = instance->GetFilterRect().Y();
float filterWidth = instance->GetFilterRect().Width();
float filterHeight = instance->GetFilterRect().Height();
float filterX = instance->GetFilterRegion().X();
float filterY = instance->GetFilterRegion().Y();
float filterWidth = instance->GetFilterRegion().Width();
float filterHeight = instance->GetFilterRegion().Height();
bool doStitch = false;
if (stitch == nsIDOMSVGFETurbulenceElement::SVG_STITCHTYPE_STITCH) {

View File

@ -66,8 +66,8 @@ public:
nsAutoFilterInstance(nsIFrame *aTarget,
nsSVGFilterFrame *aFilterFrame,
nsSVGFilterPaintCallback *aPaint,
const nsIntRect *aDirtyOutputRect,
const nsIntRect *aDirtyInputRect,
const nsIntRect *aPostFilterDirtyRect,
const nsIntRect *aPreFilterDirtyRect,
const nsIntRect *aOverrideSourceBBox,
const gfxMatrix *aOverrideUserToDeviceSpace = nsnull);
~nsAutoFilterInstance() {}
@ -83,8 +83,8 @@ private:
nsAutoFilterInstance::nsAutoFilterInstance(nsIFrame *aTarget,
nsSVGFilterFrame *aFilterFrame,
nsSVGFilterPaintCallback *aPaint,
const nsIntRect *aDirtyOutputRect,
const nsIntRect *aDirtyInputRect,
const nsIntRect *aPostFilterDirtyRect,
const nsIntRect *aPreFilterDirtyRect,
const nsIntRect *aOverrideSourceBBox,
const gfxMatrix *aOverrideUserToDeviceSpace)
{
@ -198,10 +198,10 @@ nsAutoFilterInstance::nsAutoFilterInstance(nsIFrame *aTarget,
gfxMatrix deviceToFilterSpace = filterToDeviceSpace;
deviceToFilterSpace.Invert();
nsIntRect dirtyOutputRect =
MapDeviceRectToFilterSpace(deviceToFilterSpace, filterRes, aDirtyOutputRect);
nsIntRect dirtyInputRect =
MapDeviceRectToFilterSpace(deviceToFilterSpace, filterRes, aDirtyInputRect);
nsIntRect postFilterDirtyRect =
MapDeviceRectToFilterSpace(deviceToFilterSpace, filterRes, aPostFilterDirtyRect);
nsIntRect preFilterDirtyRect =
MapDeviceRectToFilterSpace(deviceToFilterSpace, filterRes, aPreFilterDirtyRect);
nsIntRect targetBoundsDeviceSpace;
nsISVGChildFrame* svgTarget = do_QueryFrame(aTarget);
if (svgTarget) {
@ -212,8 +212,8 @@ nsAutoFilterInstance::nsAutoFilterInstance(nsIFrame *aTarget,
// space. In this case GetCoveredRegion() is not what we want since it is
// in outer-<svg> space, GetFilterBBox passes in the pre-filter bounds of
// the frame in frame space for us to use instead.
NS_ASSERTION(aDirtyInputRect, "Who passed aOverrideUserToDeviceSpace?");
targetBoundsDeviceSpace = *aDirtyInputRect;
NS_ASSERTION(aPreFilterDirtyRect, "Who passed aOverrideUserToDeviceSpace?");
targetBoundsDeviceSpace = *aPreFilterDirtyRect;
} else {
targetBoundsDeviceSpace =
svgTarget->GetCoveredRegion().ToOutsidePixels(aTarget->
@ -227,7 +227,7 @@ nsAutoFilterInstance::nsAutoFilterInstance(nsIFrame *aTarget,
mInstance = new nsSVGFilterInstance(aTarget, aPaint, filter, bbox, filterRegion,
nsIntSize(filterRes.width, filterRes.height),
filterToDeviceSpace, targetBoundsFilterSpace,
dirtyOutputRect, dirtyInputRect,
postFilterDirtyRect, preFilterDirtyRect,
primitiveUnits);
}
@ -385,13 +385,13 @@ nsSVGFilterFrame::AttributeChanged(PRInt32 aNameSpaceID,
}
nsresult
nsSVGFilterFrame::FilterPaint(nsRenderingContext *aContext,
nsIFrame *aTarget,
nsSVGFilterPaintCallback *aPaintCallback,
const nsIntRect *aDirtyRect)
nsSVGFilterFrame::PaintFilteredFrame(nsRenderingContext *aContext,
nsIFrame *aFilteredFrame,
nsSVGFilterPaintCallback *aPaintCallback,
const nsIntRect *aDirtyArea)
{
nsAutoFilterInstance instance(aTarget, this, aPaintCallback,
aDirtyRect, nsnull, nsnull);
nsAutoFilterInstance instance(aFilteredFrame, this, aPaintCallback,
aDirtyArea, nsnull, nsnull);
if (!instance.get())
return NS_OK;
@ -405,7 +405,8 @@ nsSVGFilterFrame::FilterPaint(nsRenderingContext *aContext,
}
static nsresult
TransformFilterSpaceToDeviceSpace(nsSVGFilterInstance *aInstance, nsIntRect *aRect)
TransformFilterSpaceToDeviceSpace(nsSVGFilterInstance *aInstance,
nsIntRect *aRect)
{
gfxMatrix m = aInstance->GetFilterSpaceToDeviceSpaceTransform();
gfxRect r(aRect->x, aRect->y, aRect->width, aRect->height);
@ -419,9 +420,11 @@ TransformFilterSpaceToDeviceSpace(nsSVGFilterInstance *aInstance, nsIntRect *aRe
}
nsIntRect
nsSVGFilterFrame::GetInvalidationBBox(nsIFrame *aTarget, const nsIntRect& aRect)
nsSVGFilterFrame::GetPostFilterDirtyArea(nsIFrame *aFilteredFrame,
const nsIntRect& aPreFilterDirtyRect)
{
nsAutoFilterInstance instance(aTarget, this, nsnull, nsnull, &aRect, nsnull);
nsAutoFilterInstance instance(aFilteredFrame, this, nsnull, nsnull,
&aPreFilterDirtyRect, nsnull);
if (!instance.get())
return nsIntRect();
@ -429,7 +432,7 @@ nsSVGFilterFrame::GetInvalidationBBox(nsIFrame *aTarget, const nsIntRect& aRect)
// Now we can ask the instance to compute the area of the filter output
// that's dirty.
nsIntRect dirtyRect;
nsresult rv = instance.get()->ComputeOutputDirtyRect(&dirtyRect);
nsresult rv = instance.get()->ComputePostFilterDirtyRect(&dirtyRect);
if (NS_SUCCEEDED(rv)) {
rv = TransformFilterSpaceToDeviceSpace(instance.get(), &dirtyRect);
if (NS_SUCCEEDED(rv))
@ -440,9 +443,11 @@ nsSVGFilterFrame::GetInvalidationBBox(nsIFrame *aTarget, const nsIntRect& aRect)
}
nsIntRect
nsSVGFilterFrame::GetSourceForInvalidArea(nsIFrame *aTarget, const nsIntRect& aRect)
nsSVGFilterFrame::GetPreFilterNeededArea(nsIFrame *aFilteredFrame,
const nsIntRect& aPostFilterDirtyRect)
{
nsAutoFilterInstance instance(aTarget, this, nsnull, &aRect, nsnull, nsnull);
nsAutoFilterInstance instance(aFilteredFrame, this, nsnull,
&aPostFilterDirtyRect, nsnull, nsnull);
if (!instance.get())
return nsIntRect();
@ -460,27 +465,29 @@ nsSVGFilterFrame::GetSourceForInvalidArea(nsIFrame *aTarget, const nsIntRect& aR
}
nsIntRect
nsSVGFilterFrame::GetFilterBBox(nsIFrame *aTarget,
const nsIntRect *aOverrideBBox,
const nsIntRect *aPreFilterBounds)
nsSVGFilterFrame::GetPostFilterBounds(nsIFrame *aFilteredFrame,
const nsIntRect *aOverrideBBox,
const nsIntRect *aPreFilterBounds)
{
bool overrideCTM = false;
gfxMatrix ctm;
if (aTarget->GetStateBits() & NS_FRAME_SVG_LAYOUT) {
if (aFilteredFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT) {
// For most filter operations on SVG frames we want information in
// outer-<svg> device space, but in this case we want the visual overflow
// rect relative to aTarget itself. For that we need to prevent the filter
// code using GetCanvasTM().
overrideCTM = true;
PRInt32 appUnitsPerDevPixel = aTarget->PresContext()->AppUnitsPerDevPixel();
PRInt32 appUnitsPerDevPixel =
aFilteredFrame->PresContext()->AppUnitsPerDevPixel();
float devPxPerCSSPx =
1 / nsPresContext::AppUnitsToFloatCSSPixels(appUnitsPerDevPixel);
ctm.Scale(devPxPerCSSPx, devPxPerCSSPx);
}
nsAutoFilterInstance instance(aTarget, this, nsnull, nsnull, aPreFilterBounds,
aOverrideBBox, overrideCTM ? &ctm : nsnull);
nsAutoFilterInstance instance(aFilteredFrame, this, nsnull, nsnull,
aPreFilterBounds, aOverrideBBox,
overrideCTM ? &ctm : nsnull);
if (!instance.get())
return nsIntRect();

View File

@ -45,34 +45,38 @@ public:
nsIAtom* aAttribute,
PRInt32 aModType);
nsresult FilterPaint(nsRenderingContext *aContext,
nsIFrame *aTarget, nsSVGFilterPaintCallback *aPaintCallback,
const nsIntRect* aDirtyRect);
nsresult PaintFilteredFrame(nsRenderingContext *aContext,
nsIFrame *aFilteredFrame,
nsSVGFilterPaintCallback *aPaintCallback,
const nsIntRect* aDirtyArea);
/**
* Returns the area that could change when the given rect of the source changes.
* The rectangles are relative to the origin of the outer svg, if aTarget is SVG,
* relative to aTarget itself otherwise, in device pixels.
* Returns the post-filter area that could be dirtied when the given
* pre-filter area of aFilteredFrame changes. The rects are in device pixels,
* relative to the origin of the outer-<svg> if aFilteredFrame is SVG, or
* else relative to aFilteredFrame itself.
*/
nsIntRect GetInvalidationBBox(nsIFrame *aTarget, const nsIntRect& aRect);
nsIntRect GetPostFilterDirtyArea(nsIFrame *aFilteredFrame,
const nsIntRect& aPreFilterDirtyRect);
/**
* Returns the area in device pixels that is needed from the source when
* the given area needs to be repainted.
* The rectangles are relative to the origin of the outer svg, if aTarget is SVG,
* relative to aTarget itself otherwise, in device pixels.
* Returns the pre-filter area that is needed from aFilteredFrame when the
* given post-filter area needs to be repainted. The rects are in device
* pixels, relative to the origin of the outer-<svg> if aFilteredFrame is
* SVG, or else relative to aFilteredFrame itself.
*/
nsIntRect GetSourceForInvalidArea(nsIFrame *aTarget, const nsIntRect& aRect);
nsIntRect GetPreFilterNeededArea(nsIFrame *aFilteredFrame,
const nsIntRect& aPostFilterDirtyRect);
/**
* Returns the bounding box of the post-filter area of aTarget.
* The rectangles are relative to the origin of the outer svg, if aTarget is SVG,
* relative to aTarget itself otherwise, in device pixels.
* Returns the post-filter paint bounds of aFilteredFrame. The rects are in
* device pixels, relative to the origin of the outer-<svg> if aFilteredFrame
* is SVG, or else relative to aFilteredFrame itself.
* @param aOverrideBBox overrides the normal bbox for the source, if non-null
*/
nsIntRect GetFilterBBox(nsIFrame *aTarget,
const nsIntRect *aOverrideBBox = nsnull,
const nsIntRect *aPreFilterBounds = nsnull);
nsIntRect GetPostFilterBounds(nsIFrame *aFilteredFrame,
const nsIntRect *aOverrideBBox = nsnull,
const nsIntRect *aPreFilterBounds = nsnull);
#ifdef DEBUG
NS_IMETHOD Init(nsIContent* aContent,

View File

@ -31,14 +31,14 @@ nsSVGFilterInstance::GetPrimitiveNumber(PRUint8 aCtxType, float aValue) const
switch (aCtxType) {
case nsSVGUtils::X:
return value * mFilterSpaceSize.width / mFilterRect.Width();
return value * mFilterSpaceSize.width / mFilterRegion.Width();
case nsSVGUtils::Y:
return value * mFilterSpaceSize.height / mFilterRect.Height();
return value * mFilterSpaceSize.height / mFilterRegion.Height();
case nsSVGUtils::XY:
default:
return value * nsSVGUtils::ComputeNormalizedHypotenuse(
mFilterSpaceSize.width / mFilterRect.Width(),
mFilterSpaceSize.height / mFilterRect.Height());
mFilterSpaceSize.width / mFilterRegion.Width(),
mFilterSpaceSize.height / mFilterRegion.Height());
}
}
@ -83,27 +83,27 @@ nsSVGFilterInstance::CreateImage()
gfxRect
nsSVGFilterInstance::UserSpaceToFilterSpace(const gfxRect& aRect) const
{
gfxRect r = aRect - mFilterRect.TopLeft();
r.Scale(mFilterSpaceSize.width / mFilterRect.Width(),
mFilterSpaceSize.height / mFilterRect.Height());
gfxRect r = aRect - mFilterRegion.TopLeft();
r.Scale(mFilterSpaceSize.width / mFilterRegion.Width(),
mFilterSpaceSize.height / mFilterRegion.Height());
return r;
}
gfxPoint
nsSVGFilterInstance::FilterSpaceToUserSpace(const gfxPoint& aPt) const
{
return gfxPoint(aPt.x * mFilterRect.Width() / mFilterSpaceSize.width + mFilterRect.X(),
aPt.y * mFilterRect.Height() / mFilterSpaceSize.height + mFilterRect.Y());
return gfxPoint(aPt.x * mFilterRegion.Width() / mFilterSpaceSize.width + mFilterRegion.X(),
aPt.y * mFilterRegion.Height() / mFilterSpaceSize.height + mFilterRegion.Y());
}
gfxMatrix
nsSVGFilterInstance::GetUserSpaceToFilterSpaceTransform() const
{
gfxFloat widthScale = mFilterSpaceSize.width / mFilterRect.Width();
gfxFloat heightScale = mFilterSpaceSize.height / mFilterRect.Height();
gfxFloat widthScale = mFilterSpaceSize.width / mFilterRegion.Width();
gfxFloat heightScale = mFilterSpaceSize.height / mFilterRegion.Height();
return gfxMatrix(widthScale, 0.0f,
0.0f, heightScale,
-mFilterRect.X() * widthScale, -mFilterRect.Y() * heightScale);
-mFilterRegion.X() * widthScale, -mFilterRegion.Y() * heightScale);
}
void
@ -277,7 +277,7 @@ nsSVGFilterInstance::ComputeNeededBoxes()
// In the end, we need whatever the final filter primitive will draw that
// intersects the destination dirty area.
mPrimitives[mPrimitives.Length() - 1].mResultNeededBox.IntersectRect(
mPrimitives[mPrimitives.Length() - 1].mResultBoundingBox, mDirtyOutputRect);
mPrimitives[mPrimitives.Length() - 1].mResultBoundingBox, mPostFilterDirtyRect);
for (PRInt32 i = mPrimitives.Length() - 1; i >= 0; --i) {
PrimitiveInfo* info = &mPrimitives[i];
@ -522,9 +522,9 @@ nsSVGFilterInstance::Render(gfxASurface** aOutput)
}
nsresult
nsSVGFilterInstance::ComputeOutputDirtyRect(nsIntRect* aDirty)
nsSVGFilterInstance::ComputePostFilterDirtyRect(nsIntRect* aPostFilterDirtyRect)
{
*aDirty = nsIntRect();
*aPostFilterDirtyRect = nsIntRect();
nsresult rv = BuildSources();
if (NS_FAILED(rv))
@ -541,12 +541,12 @@ nsSVGFilterInstance::ComputeOutputDirtyRect(nsIntRect* aDirty)
ComputeResultBoundingBoxes();
mSourceColorAlpha.mResultChangeBox = mDirtyInputRect;
mSourceAlpha.mResultChangeBox = mDirtyInputRect;
mSourceColorAlpha.mResultChangeBox = mPreFilterDirtyRect;
mSourceAlpha.mResultChangeBox = mPreFilterDirtyRect;
ComputeResultChangeBoxes();
PrimitiveInfo* result = &mPrimitives[mPrimitives.Length() - 1];
*aDirty = result->mResultChangeBox;
*aPostFilterDirtyRect = result->mResultChangeBox;
return NS_OK;
}

View File

@ -34,9 +34,13 @@ class nsSVGFilterPaintCallback;
*
* Definition of "filter space": filter space is a coordinate system that is
* aligned with the user space of the filtered element, with its origin located
* at the top left of the filter region (as returned by GetFilterRect,
* specifically), and with one unit equal in size to one pixel of the offscreen
* surface into which the filter output would/will be painted.
* at the top left of the filter region (as specified by our ctor's
* aFilterRegion, and returned by our GetFilterRegion, specifically), and with
* one unit equal in size to one pixel of the offscreen surface into which the
* filter output would/will be painted.
*
* The definition of "filter region" can be found here:
* http://www.w3.org/TR/SVG11/filters.html#FilterEffectsRegion
*/
class NS_STACK_CLASS nsSVGFilterInstance
{
@ -49,7 +53,7 @@ public:
* element.
* @param aTargetBBox The filtered element's bbox, in the filtered element's
* user space.
* @param aFilterRect The "filter region", in the filtered element's user
* @param aFilterRegion The "filter region", in the filtered element's user
* space. The caller must have already expanded the region out so that its
* edges coincide with pixel boundaries in the offscreen surface that
* would/will be created to paint the filter output.
@ -59,36 +63,36 @@ public:
* space to outer-<svg> device space.
* @param aTargetBounds The pre-filter paint bounds of the filtered element,
* in filter space.
* @param aDirtyOutputRect [optional] The bounds of the post-filter area that
* has to be repainted, in filter space. Only required if you will call
* ComputeSourceNeededRect() or Render().
* @param aDirtyInputRect [optional] The bounds of the pre-filter area of the
* filtered element that changed, in filter space. Only required if you
* will call ComputeOutputDirtyRect().
* @param aPostFilterDirtyRect [optional] The bounds of the post-filter area
* that has to be repainted, in filter space. Only required if you will
* call ComputeSourceNeededRect() or Render().
* @param aPreFilterDirtyRect [optional] The bounds of the pre-filter area of
* the filtered element that changed, in filter space. Only required if you
* will call ComputePostFilterDirtyRect().
* @param aPrimitiveUnits The value from the 'primitiveUnits' attribute.
*/
nsSVGFilterInstance(nsIFrame *aTargetFrame,
nsSVGFilterPaintCallback *aPaintCallback,
const nsSVGFilterElement *aFilterElement,
const gfxRect &aTargetBBox,
const gfxRect& aFilterRect,
const gfxRect& aFilterRegion,
const nsIntSize& aFilterSpaceSize,
const gfxMatrix &aFilterSpaceToDeviceSpaceTransform,
const nsIntRect& aTargetBounds,
const nsIntRect& aDirtyOutputRect,
const nsIntRect& aDirtyInputRect,
const nsIntRect& aPostFilterDirtyRect,
const nsIntRect& aPreFilterDirtyRect,
PRUint16 aPrimitiveUnits) :
mTargetFrame(aTargetFrame),
mPaintCallback(aPaintCallback),
mFilterElement(aFilterElement),
mTargetBBox(aTargetBBox),
mFilterSpaceToDeviceSpaceTransform(aFilterSpaceToDeviceSpaceTransform),
mFilterRect(aFilterRect),
mFilterRegion(aFilterRegion),
mFilterSpaceSize(aFilterSpaceSize),
mSurfaceRect(nsIntPoint(0, 0), aFilterSpaceSize),
mTargetBounds(aTargetBounds),
mDirtyOutputRect(aDirtyOutputRect),
mDirtyInputRect(aDirtyInputRect),
mPostFilterDirtyRect(aPostFilterDirtyRect),
mPreFilterDirtyRect(aPreFilterDirtyRect),
mPrimitiveUnits(aPrimitiveUnits) {
}
@ -98,7 +102,7 @@ public:
* coincide with pixel boundaries of the offscreen surface into which the
* filtered output would/will be painted.
*/
gfxRect GetFilterRect() const { return mFilterRect; }
gfxRect GetFilterRegion() const { return mFilterRegion; }
/**
* Returns the size of the user specified "filter region", in filter space.
@ -126,25 +130,25 @@ public:
* Allocates a gfxASurface, renders the filtered element into the surface,
* and then returns the surface via the aOutput outparam. The area that
* needs to be painted must have been specified before calling this method
* by passing it as the aDirtyOutputRect argument to the
* by passing it as the aPostFilterDirtyRect argument to the
* nsSVGFilterInstance constructor.
*/
nsresult Render(gfxASurface** aOutput);
/**
* Sets the aDirty outparam to the post-filter bounds in filter space of the
* area that would be dirtied by mTargetFrame when a given pre-filter area of
* mTargetFrame is dirtied. The pre-filter area must have been specified
* before calling this method by passing it as the aDirtyInputRect argument
* to the nsSVGFilterInstance constructor.
* Sets the aPostFilterDirtyRect outparam to the post-filter bounds in filter
* space of the area that would be dirtied by mTargetFrame when a given
* pre-filter area of mTargetFrame is dirtied. The pre-filter area must have
* been specified before calling this method by passing it as the
* aPreFilterDirtyRect argument to the nsSVGFilterInstance constructor.
*/
nsresult ComputeOutputDirtyRect(nsIntRect* aDirty);
nsresult ComputePostFilterDirtyRect(nsIntRect* aPostFilterDirtyRect);
/**
* Sets the aDirty outparam to the pre-filter bounds in filter space of the
* area of mTargetFrame that is needed in order to paint the filtered output
* for a given post-filter dirtied area. The post-filter area must have been
* specified before calling this method by passing it as the aDirtyOutputRect
* specified before calling this method by passing it as the aPostFilterDirtyRect
* argument to the nsSVGFilterInstance constructor.
*/
nsresult ComputeSourceNeededRect(nsIntRect* aDirty);
@ -290,14 +294,14 @@ private:
/**
* Computes the filter space bounds of the areas that we actually *need* from
* each filter primitive's output, based on the value of mDirtyOutputRect.
* each filter primitive's output, based on the value of mPostFilterDirtyRect.
* This sets mResultNeededBox on the items in the filter graph.
*/
void ComputeNeededBoxes();
/**
* Computes the filter space bounds of the area of each filter primitive
* that will change, based on the value of mDirtyInputRect.
* that will change, based on the value of mPreFilterDirtyRect.
* This sets mResultChangeBox on the items in the filter graph.
*/
void ComputeResultChangeBoxes();
@ -360,7 +364,7 @@ private:
gfxRect mTargetBBox;
gfxMatrix mFilterSpaceToDeviceSpaceTransform;
gfxRect mFilterRect;
gfxRect mFilterRegion;
nsIntSize mFilterSpaceSize;
nsIntRect mSurfaceRect;
@ -375,7 +379,7 @@ private:
* bounds of the dirty area that needs to be repainted. (As bounds-of-bounds,
* this may be a fair bit bigger than we actually need, unfortunately.)
*/
nsIntRect mDirtyOutputRect;
nsIntRect mPostFilterDirtyRect;
/**
* If set, this is the filter space bounds of the outer-<svg> device bounds
@ -383,7 +387,7 @@ private:
* bounds-of-bounds, this may be a fair bit bigger than we actually need,
* unfortunately.)
*/
nsIntRect mDirtyInputRect;
nsIntRect mPreFilterDirtyRect;
/**
* The 'primitiveUnits' attribute value (objectBoundingBox or userSpaceOnUse).

View File

@ -100,7 +100,7 @@ nsSVGIntegrationUtils::ComputeFrameEffectsRect(nsIFrame* aFrame,
// r is relative to user space
PRUint32 appUnitsPerDevPixel = aFrame->PresContext()->AppUnitsPerDevPixel();
nsIntRect p = r.ToOutsidePixels(appUnitsPerDevPixel);
p = filterFrame->GetFilterBBox(firstFrame, &p);
p = filterFrame->GetPostFilterBounds(firstFrame, &p);
r = p.ToAppUnits(appUnitsPerDevPixel);
// Make it relative to aFrame again
return r + userSpaceRect.TopLeft() - aFrame->GetOffsetTo(firstFrame);
@ -137,7 +137,7 @@ nsSVGIntegrationUtils::GetInvalidAreaForChangedSource(nsIFrame* aFrame,
nsPoint offset = aFrame->GetOffsetTo(firstFrame) - userSpaceRect.TopLeft();
nsRect r = aInvalidRect + offset;
nsIntRect p = r.ToOutsidePixels(appUnitsPerDevPixel);
p = filterFrame->GetInvalidationBBox(firstFrame, p);
p = filterFrame->GetPostFilterDirtyArea(firstFrame, p);
r = p.ToAppUnits(appUnitsPerDevPixel);
return r - offset;
}
@ -160,7 +160,7 @@ nsSVGIntegrationUtils::GetRequiredSourceForInvalidArea(nsIFrame* aFrame,
nsPoint offset = aFrame->GetOffsetTo(firstFrame) - userSpaceRect.TopLeft();
nsRect r = aDamageRect + offset;
nsIntRect p = r.ToOutsidePixels(appUnitsPerDevPixel);
p = filterFrame->GetSourceForInvalidArea(firstFrame, p);
p = filterFrame->GetPreFilterNeededArea(firstFrame, p);
r = p.ToAppUnits(appUnitsPerDevPixel);
return r - offset;
}
@ -279,10 +279,11 @@ nsSVGIntegrationUtils::PaintFramesWithEffects(nsRenderingContext* aCtx,
/* Paint the child */
if (filterFrame) {
RegularFramePaintCallback paint(aBuilder, aInnerList, aEffectsFrame,
userSpaceRect.TopLeft());
nsIntRect r = (aDirtyRect - userSpaceRect.TopLeft()).ToOutsidePixels(appUnitsPerDevPixel);
filterFrame->FilterPaint(aCtx, aEffectsFrame, &paint, &r);
RegularFramePaintCallback callback(aBuilder, aInnerList, aEffectsFrame,
userSpaceRect.TopLeft());
nsIntRect dirtyRect = (aDirtyRect - userSpaceRect.TopLeft())
.ToOutsidePixels(appUnitsPerDevPixel);
filterFrame->PaintFilteredFrame(aCtx, aEffectsFrame, &callback, &dirtyRect);
} else {
gfx->SetMatrix(matrixAutoSaveRestore.Matrix());
aInnerList->PaintForFrame(aBuilder, aCtx, aEffectsFrame,

View File

@ -580,20 +580,20 @@ nsSVGUtils::GetNearestSVGViewport(nsIFrame *aFrame)
nsRect
nsSVGUtils::GetPostFilterVisualOverflowRect(nsIFrame *aFrame,
const nsRect &aUnfilteredRect)
const nsRect &aPreFilterRect)
{
NS_ABORT_IF_FALSE(aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT,
"Called on invalid frame type");
nsSVGFilterFrame *filter = nsSVGEffects::GetFilterFrame(aFrame);
if (!filter) {
return aUnfilteredRect;
return aPreFilterRect;
}
PRInt32 appUnitsPerDevPixel = aFrame->PresContext()->AppUnitsPerDevPixel();
nsIntRect unfilteredRect =
aUnfilteredRect.ToOutsidePixels(appUnitsPerDevPixel);
nsIntRect rect = filter->GetFilterBBox(aFrame, nsnull, &unfilteredRect);
nsIntRect preFilterRect =
aPreFilterRect.ToOutsidePixels(appUnitsPerDevPixel);
nsIntRect rect = filter->GetPostFilterBounds(aFrame, nsnull, &preFilterRect);
nsRect r = rect.ToAppUnits(appUnitsPerDevPixel) - aFrame->GetPosition();
return r;
}
@ -1240,7 +1240,8 @@ nsSVGUtils::PaintFrameWithEffects(nsRenderingContext *aContext,
/* Paint the child */
if (filterFrame) {
SVGPaintCallback paintCallback;
filterFrame->FilterPaint(aContext, aFrame, &paintCallback, aDirtyRect);
filterFrame->PaintFilteredFrame(aContext, aFrame, &paintCallback,
aDirtyRect);
} else {
svgChildFrame->PaintSVG(aContext, aDirtyRect);
}