Bug 779029: Try to respect EXTEND_NONE when masking. r=jrmuizel

--HG--
extra : rebase_source : 0634d90f2c580fd4cc1ad73fb5b3406a6afda964
This commit is contained in:
Bas Schouten 2013-05-12 15:03:12 +01:00
parent 35235709d9
commit fc4d747155
3 changed files with 50 additions and 1 deletions

View File

@ -1404,7 +1404,48 @@ gfxContext::Mask(gfxPattern *pattern)
if (mCairo) {
cairo_mask(mCairo, pattern->CairoPattern());
} else {
bool needsClip = false;
if (pattern->Extend() == gfxPattern::EXTEND_NONE) {
// In this situation the mask will be fully transparent (i.e. nothing
// will be drawn) outside of the bounds of the surface. We can support
// that by clipping out drawing to that area.
Rect surfaceSourceRect;
if (!pattern->IsAzure() &&
pattern->GetType() == gfxPattern::PATTERN_SURFACE)
{
needsClip = true;
nsRefPtr<gfxASurface> surf = pattern->GetSurface();
gfxPoint offset = surf->GetDeviceOffset();
surfaceSourceRect = Rect(-offset.x, -offset.y, surf->GetSize().width, surf->GetSize().height);
} else if (pattern->IsAzure()) {
// This is an Azure pattern. i.e. this was the result of a PopGroup and
// then the extend mode was changed to EXTEND_NONE.
// XXX - We may need some additional magic here in theory to support
// device offsets in these patterns, but no problems have been observed
// yet because of this. And it would complicate things a little further.
needsClip = true;
RefPtr<SourceSurface> surf = pattern->GetAzureSurface();
surfaceSourceRect = Rect(0, 0, surf->GetSize().width, surf->GetSize().height);
}
if (needsClip) {
Matrix mat = ToMatrix(pattern->GetMatrix());
mat.Invert();
mat = mat * GetDTTransform();
mDT->SetTransform(mat);
mDT->PushClipRect(surfaceSourceRect);
mDT->SetTransform(GetDTTransform());
}
}
mDT->Mask(GeneralPattern(this), *pattern->GetPattern(mDT), DrawOptions(1.0f, CurrentState().op, CurrentState().aaMode));
if (needsClip) {
mDT->PopClip();
}
}
}
@ -1420,10 +1461,14 @@ gfxContext::Mask(gfxASurface *surface, const gfxPoint& offset)
gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(mDT, surface);
gfxPoint pt = surface->GetDeviceOffset();
// We clip here to bind to the mask surface bounds, see above.
mDT->PushClipRect(Rect(offset.x - pt.x, offset.y - pt.y, sourceSurf->GetSize().width, sourceSurf->GetSize().height));
mDT->Mask(GeneralPattern(this),
SurfacePattern(sourceSurf, EXTEND_CLAMP,
Matrix(1.0f, 0, 0, 1.0f, Float(offset.x - pt.x), Float(offset.y - pt.y))),
DrawOptions(1.0f, CurrentState().op, CurrentState().aaMode));
mDT->PopClip();
}
}

View File

@ -101,6 +101,10 @@ public:
already_AddRefed<gfxASurface> GetSurface();
bool IsAzure() { return !mPattern; }
mozilla::TemporaryRef<mozilla::gfx::SourceSurface> GetAzureSurface() { return mSourceSurface; }
protected:
cairo_pattern_t *mPattern;

View File

@ -186,7 +186,7 @@ fuzzy-if(Android,9,980) == gradient-live-01d.svg gradient-live-01-ref.svg
== marker-orientation-01.svg marker-orientation-01-ref.svg
== mask-basic-01.svg pass.svg
== mask-basic-02.svg mask-basic-02-ref.svg
#== mask-basic-03.svg pass.svg
== mask-basic-03.svg pass.svg
== mask-extref-dataURI-01.svg pass.svg
== mask-containing-masked-content-01.svg pass.svg
== mask-transformed-01.svg mask-transformed-01-ref.svg