Bug 852100 - Part 1. Bring in pixel snap offset while painting source image.
MozReview-Commit-ID: D58KaMOjeEi
--- a/layout/svg/nsFilterInstance.cpp
+++ b/layout/svg/nsFilterInstance.cpp
@@ -369,17 +369,18 @@ nsFilterInstance::ComputeNeededBoxes()
UpdateNeededBounds(sourceGraphicNeededRegion, mSourceGraphic.mNeededBounds);
UpdateNeededBounds(fillPaintNeededRegion, mFillPaint.mNeededBounds);
UpdateNeededBounds(strokePaintNeededRegion, mStrokePaint.mNeededBounds);
}
void
nsFilterInstance::BuildSourcePaint(SourceInfo *aSource,
- imgDrawingParams& aImgParams)
+ imgDrawingParams& aImgParams,
+ const Point& aOffset)
{
MOZ_ASSERT(mTargetFrame);
nsIntRect neededRect = aSource->mNeededBounds;
if (neededRect.IsEmpty()) {
return;
}
RefPtr<DrawTarget> offscreenDT =
@@ -389,17 +390,18 @@ nsFilterInstance::BuildSourcePaint(Sourc
return;
}
RefPtr<gfxContext> ctx = gfxContext::CreateOrNull(offscreenDT);
MOZ_ASSERT(ctx); // already checked the draw target above
gfxContextAutoSaveRestore saver(ctx);
ctx->SetMatrix(mPaintTransform *
- gfxMatrix::Translation(-neededRect.TopLeft()));
+ gfxMatrix::Translation(-neededRect.TopLeft()) *
+ gfxMatrix::Translation(aOffset.x, aOffset.y));
GeneralPattern pattern;
if (aSource == &mFillPaint) {
nsSVGUtils::MakeFillPatternFor(mTargetFrame, ctx, &pattern, aImgParams);
} else if (aSource == &mStrokePaint) {
nsSVGUtils::MakeStrokePatternFor(mTargetFrame, ctx, &pattern, aImgParams);
}
if (pattern.GetPattern()) {
@@ -407,29 +409,31 @@ nsFilterInstance::BuildSourcePaint(Sourc
pattern);
}
aSource->mSourceSurface = offscreenDT->Snapshot();
aSource->mSurfaceRect = neededRect;
}
void
-nsFilterInstance::BuildSourcePaints(imgDrawingParams& aImgParams)
+nsFilterInstance::BuildSourcePaints(imgDrawingParams& aImgParams,
+ const Point& aOffset)
{
if (!mFillPaint.mNeededBounds.IsEmpty()) {
- BuildSourcePaint(&mFillPaint, aImgParams);
+ BuildSourcePaint(&mFillPaint, aImgParams, aOffset);
}
if (!mStrokePaint.mNeededBounds.IsEmpty()) {
- BuildSourcePaint(&mStrokePaint, aImgParams);
+ BuildSourcePaint(&mStrokePaint, aImgParams, aOffset);
}
}
void
-nsFilterInstance::BuildSourceImage(imgDrawingParams& aImgParams)
+nsFilterInstance::BuildSourceImage(imgDrawingParams& aImgParams,
+ const Point& aOffset)
{
MOZ_ASSERT(mTargetFrame);
nsIntRect neededRect = mSourceGraphic.mNeededBounds;
if (neededRect.IsEmpty()) {
return;
}
@@ -459,17 +463,18 @@ nsFilterInstance::BuildSourceImage(imgDr
// code more complex while being hard to get right without introducing
// subtle bugs, and in practice it probably makes no real difference.)
RefPtr<gfxContext> ctx = gfxContext::CreateOrNull(offscreenDT);
MOZ_ASSERT(ctx); // already checked the draw target above
gfxMatrix devPxToCssPxTM = nsSVGUtils::GetCSSPxToDevPxMatrix(mTargetFrame);
DebugOnly<bool> invertible = devPxToCssPxTM.Invert();
MOZ_ASSERT(invertible);
ctx->SetMatrix(devPxToCssPxTM * mPaintTransform *
- gfxMatrix::Translation(-neededRect.TopLeft()));
+ gfxMatrix::Translation(-neededRect.TopLeft()) *
+ gfxMatrix::Translation(aOffset.x, aOffset.y));
mPaintCallback->Paint(*ctx, mTargetFrame, mPaintTransform, &dirty, aImgParams);
mSourceGraphic.mSourceSurface = offscreenDT->Snapshot();
mSourceGraphic.mSurfaceRect = neededRect;
}
void
@@ -482,33 +487,35 @@ nsFilterInstance::Render(DrawTarget* aDr
return;
}
nsIntRect filterRect =
mPostFilterDirtyRegion.GetBounds().Intersect(OutputFilterSpaceBounds());
if (filterRect.IsEmpty() || mPaintTransform.IsSingular()) {
return;
}
+ Matrix originMatrix = aDrawTarget->GetTransform();
+ Point snapOffset(originMatrix._31 - int(originMatrix._31),
+ originMatrix._32 - int(originMatrix._32));
AutoRestoreTransform autoRestoreTransform(aDrawTarget);
- Matrix newTM =
- aDrawTarget->GetTransform().PreTranslate(filterRect.x, filterRect.y);
+ Matrix newTM = originMatrix.PreTranslate(filterRect.x, filterRect.y);
aDrawTarget->SetTransform(newTM);
ComputeNeededBoxes();
- BuildSourceImage(aImgParams);
- BuildSourcePaints(aImgParams);
+ BuildSourceImage(aImgParams, snapOffset);
+ BuildSourcePaints(aImgParams, snapOffset);
FilterSupport::RenderFilterDescription(
aDrawTarget, mFilterDescription, IntRectToRect(filterRect),
mSourceGraphic.mSourceSurface, mSourceGraphic.mSurfaceRect,
mFillPaint.mSourceSurface, mFillPaint.mSurfaceRect,
mStrokePaint.mSourceSurface, mStrokePaint.mSurfaceRect,
- mInputImages, Point(0, 0));
+ mInputImages, Point(-snapOffset.x, -snapOffset.y));
}
nsRegion
nsFilterInstance::ComputePostFilterDirtyRegion()
{
if (mPreFilterDirtyRegion.IsEmpty() || mPrimitiveDescriptions.IsEmpty()) {
return nsRegion();
}
--- a/layout/svg/nsFilterInstance.h
+++ b/layout/svg/nsFilterInstance.h
@@ -51,16 +51,17 @@ class nsFilterInstance
{
typedef mozilla::gfx::IntRect IntRect;
typedef mozilla::gfx::SourceSurface SourceSurface;
typedef mozilla::gfx::DrawTarget DrawTarget;
typedef mozilla::gfx::FilterPrimitiveDescription FilterPrimitiveDescription;
typedef mozilla::gfx::FilterDescription FilterDescription;
typedef mozilla::dom::UserSpaceMetrics UserSpaceMetrics;
typedef mozilla::image::imgDrawingParams imgDrawingParams;
+ typedef mozilla::gfx::Point Point;
public:
/**
* Create a FilterDescription for the supplied filter. All coordinates in
* the description are in filter space.
* @param aFilterInputIsTainted Describes whether the SourceImage / SourceAlpha
* input is tainted. This affects whether feDisplacementMap will respect
* the filter input as its map input, and it affects the IsTainted() state
* on the filter primitives in the FilterDescription. "Tainted" is a term
@@ -216,30 +217,31 @@ private:
// Set by BuildSourceImage / BuildSourcePaint.
IntRect mSurfaceRect;
};
/**
* Creates a SourceSurface for either the FillPaint or StrokePaint graph
* nodes
*/
- void BuildSourcePaint(SourceInfo *aPrimitive, imgDrawingParams& aImgParams);
+ void BuildSourcePaint(SourceInfo *aPrimitive, imgDrawingParams& aImgParams,
+ const Point& aOffset);
/**
* Creates a SourceSurface for either the FillPaint and StrokePaint graph
* nodes, fills its contents and assigns it to mFillPaint.mSourceSurface and
* mStrokePaint.mSourceSurface respectively.
*/
- void BuildSourcePaints(imgDrawingParams& aImgParams);
+ void BuildSourcePaints(imgDrawingParams& aImgParams, const Point& aOffset);
/**
* Creates the SourceSurface for the SourceGraphic graph node, paints its
* contents, and assigns it to mSourceGraphic.mSourceSurface.
*/
- void BuildSourceImage(imgDrawingParams& aImgParams);
+ void BuildSourceImage(imgDrawingParams& aImgParams, const Point& aOffset);
/**
* Build the list of FilterPrimitiveDescriptions that describes the filter's
* filter primitives and their connections. This populates
* mPrimitiveDescriptions and mInputImages. aFilterInputIsTainted describes
* whether the SourceGraphic is tainted.
*/
nsresult BuildPrimitives(const nsTArray<nsStyleFilter>& aFilterChain,