diff --git a/gfx/thebes/gfxDrawable.cpp b/gfx/thebes/gfxDrawable.cpp index ea2eaf785d48..56bbb9c01779 100644 --- a/gfx/thebes/gfxDrawable.cpp +++ b/gfx/thebes/gfxDrawable.cpp @@ -134,6 +134,12 @@ gfxSurfaceDrawable::Draw(gfxContext* aContext, return true; } +already_AddRefed +gfxSurfaceDrawable::GetAsImageSurface() +{ + return mSurface->GetAsImageSurface(); +} + gfxCallbackDrawable::gfxCallbackDrawable(gfxDrawingCallback* aCallback, const gfxIntSize aSize) : gfxDrawable(aSize) diff --git a/gfx/thebes/gfxDrawable.h b/gfx/thebes/gfxDrawable.h index f159a4768538..e67bfaaa53db 100644 --- a/gfx/thebes/gfxDrawable.h +++ b/gfx/thebes/gfxDrawable.h @@ -15,6 +15,7 @@ #include "gfxPattern.h" class gfxASurface; +class gfxImageSurface; class gfxContext; /** @@ -41,6 +42,7 @@ public: bool aRepeat, const gfxPattern::GraphicsFilter& aFilter, const gfxMatrix& aTransform = gfxMatrix()) = 0; + virtual already_AddRefed GetAsImageSurface() { return nullptr; } virtual gfxIntSize Size() { return mSize; } protected: @@ -62,6 +64,8 @@ public: bool aRepeat, const gfxPattern::GraphicsFilter& aFilter, const gfxMatrix& aTransform = gfxMatrix()); + + virtual already_AddRefed GetAsImageSurface(); protected: nsRefPtr mSurface; diff --git a/gfx/thebes/gfxImageSurface.cpp b/gfx/thebes/gfxImageSurface.cpp index c402fdc3f05f..724741c9d08d 100644 --- a/gfx/thebes/gfxImageSurface.cpp +++ b/gfx/thebes/gfxImageSurface.cpp @@ -297,6 +297,8 @@ gfxImageSurface::GetSubimage(const gfxRect& aRect) { gfxRect r(aRect); r.Round(); + MOZ_ASSERT(gfxRect(0, 0, mSize.width, mSize.height).Contains(r)); + unsigned char* subData = Data() + (Stride() * (int)r.Y()) + (int)r.X() * gfxASurface::BytePerPixelFromFormat(Format()); diff --git a/gfx/thebes/gfxUtils.cpp b/gfx/thebes/gfxUtils.cpp index 7633765fc663..d46236af037d 100644 --- a/gfx/thebes/gfxUtils.cpp +++ b/gfx/thebes/gfxUtils.cpp @@ -245,16 +245,23 @@ CreateSamplingRestrictedDrawable(gfxDrawable* aDrawable, if (needed.IsEmpty()) return nullptr; + nsRefPtr temp; gfxIntSize size(int32_t(needed.Width()), int32_t(needed.Height())); - nsRefPtr temp = - gfxPlatform::GetPlatform()->CreateOffscreenSurface(size, gfxASurface::ContentFromFormat(aFormat)); - if (!temp || temp->CairoStatus()) - return nullptr; - nsRefPtr tmpCtx = new gfxContext(temp); - tmpCtx->SetOperator(OptimalFillOperator()); - aDrawable->Draw(tmpCtx, needed - needed.TopLeft(), true, - gfxPattern::FILTER_FAST, gfxMatrix().Translate(needed.TopLeft())); + nsRefPtr image = aDrawable->GetAsImageSurface(); + if (image && gfxRect(0, 0, image->GetSize().width, image->GetSize().height).Contains(needed)) { + temp = image->GetSubimage(needed); + } else { + temp = + gfxPlatform::GetPlatform()->CreateOffscreenSurface(size, gfxASurface::ContentFromFormat(aFormat)); + if (!temp || temp->CairoStatus()) + return nullptr; + + nsRefPtr tmpCtx = new gfxContext(temp); + tmpCtx->SetOperator(OptimalFillOperator()); + aDrawable->Draw(tmpCtx, needed - needed.TopLeft(), true, + gfxPattern::FILTER_FAST, gfxMatrix().Translate(needed.TopLeft())); + } nsRefPtr drawable = new gfxSurfaceDrawable(temp, size, gfxMatrix().Translate(-needed.TopLeft()));