Bug 944571 - Part 1: Convert gfxAlphaBoxBlur to use Moz2D surfaces instead of Thebes. r=Bas

This commit is contained in:
Matt Woodrow 2013-10-02 17:20:47 +13:00
parent df8c35f9a9
commit 3b444e24fd
3 changed files with 61 additions and 30 deletions

View File

@ -6,8 +6,10 @@
#include "gfxBlur.h"
#include "gfxContext.h"
#include "gfxImageSurface.h"
#include "gfxPlatform.h"
#include "mozilla/gfx/Blur.h"
#include "mozilla/gfx/2D.h"
using namespace mozilla::gfx;
@ -19,7 +21,6 @@ gfxAlphaBoxBlur::gfxAlphaBoxBlur()
gfxAlphaBoxBlur::~gfxAlphaBoxBlur()
{
mContext = nullptr;
mImageSurface = nullptr;
delete mBlur;
}
@ -58,23 +59,30 @@ gfxAlphaBoxBlur::Init(const gfxRect& aRect,
// Make an alpha-only surface to draw on. We will play with the data after
// everything is drawn to create a blur effect.
mImageSurface = new gfxImageSurface(gfxIntSize(size.width, size.height),
gfxImageFormatA8,
mBlur->GetStride(),
blurDataSize,
true);
if (mImageSurface->CairoStatus())
return nullptr;
mData = new unsigned char[blurDataSize];
memset(mData, 0, blurDataSize);
RefPtr<DrawTarget> dt =
gfxPlatform::GetPlatform()->CreateDrawTargetForData(mData, size,
mBlur->GetStride(),
FORMAT_A8);
if (!dt) {
nsRefPtr<gfxImageSurface> image =
new gfxImageSurface(mData,
gfxIntSize(size.width, size.height),
mBlur->GetStride(),
gfxImageFormatA8);
dt = Factory::CreateDrawTargetForCairoSurface(image->CairoSurface(), size);
if (!dt) {
return nullptr;
}
}
IntRect irect = mBlur->GetRect();
gfxPoint topleft(irect.TopLeft().x, irect.TopLeft().y);
// Use a device offset so callers don't need to worry about translating
// coordinates, they can draw as if this was part of the destination context
// at the coordinates of rect.
mImageSurface->SetDeviceOffset(-topleft);
mContext = new gfxContext(mImageSurface);
mContext = new gfxContext(dt);
mContext->Translate(-topleft);
return mContext;
}
@ -85,24 +93,44 @@ gfxAlphaBoxBlur::Paint(gfxContext* aDestinationCtx)
if (!mContext)
return;
mBlur->Blur(mImageSurface->Data());
mBlur->Blur(mData);
mozilla::gfx::Rect* dirtyrect = mBlur->GetDirtyRect();
mozilla::gfx::Rect* dirtyRect = mBlur->GetDirtyRect();
DrawTarget *dest = aDestinationCtx->GetDrawTarget();
if (!dest) {
NS_ERROR("Blurring not supported for Thebes contexts!");
return;
}
RefPtr<SourceSurface> mask = dest->CreateSourceSurfaceFromData(mData,
mBlur->GetSize(),
mBlur->GetStride(),
FORMAT_A8);
if (!mask) {
NS_ERROR("Failed to create mask!");
return;
}
nsRefPtr<gfxPattern> thebesPat = aDestinationCtx->GetPattern();
Pattern* pat = thebesPat->GetPattern(dest, nullptr);
Matrix oldTransform = dest->GetTransform();
Matrix newTransform = oldTransform;
newTransform.Translate(mBlur->GetRect().x, mBlur->GetRect().y);
// Avoid a semi-expensive clip operation if we can, otherwise
// clip to the dirty rect
if (dirtyrect) {
aDestinationCtx->Save();
aDestinationCtx->NewPath();
gfxRect dirty(dirtyrect->x, dirtyrect->y, dirtyrect->width, dirtyrect->height);
gfxRect imageRect(-mImageSurface->GetDeviceOffset(), mImageSurface->GetSize());
dirty.IntersectRect(dirty, imageRect);
aDestinationCtx->Rectangle(dirty);
aDestinationCtx->Clip();
aDestinationCtx->Mask(mImageSurface, gfxPoint());
aDestinationCtx->Restore();
} else {
aDestinationCtx->Mask(mImageSurface, gfxPoint());
if (dirtyRect) {
dest->PushClipRect(*dirtyRect);
}
dest->SetTransform(newTransform);
dest->MaskSurface(*pat, mask, Point(0, 0));
dest->SetTransform(oldTransform);
if (dirtyRect) {
dest->PopClip();
}
}

View File

@ -10,6 +10,7 @@
#include "nsSize.h"
#include "nsAutoPtr.h"
#include "gfxPoint.h"
#include "mozilla/RefPtr.h"
class gfxContext;
class gfxImageSurface;
@ -21,6 +22,8 @@ class gfxMatrix;
namespace mozilla {
namespace gfx {
class AlphaBoxBlur;
class SourceSurface;
class DrawTarget;
}
}
@ -138,7 +141,7 @@ protected:
/**
* The temporary alpha surface.
*/
nsRefPtr<gfxImageSurface> mImageSurface;
nsAutoArrayPtr<unsigned char> mData;
/**
* The object that actually does the blurring for us.

View File

@ -4780,7 +4780,7 @@ nsContextBoxBlur::Init(const nsRect& aRect, nscoord aSpreadRadius,
if (mContext) {
// we don't need to blur if skipRect is equal to rect
// and mContext will be nullptr
mContext->SetMatrix(transform);
mContext->Multiply(transform);
}
return mContext;
}