mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 11:55:49 +00:00
Bug 944571 - Part 1: Convert gfxAlphaBoxBlur to use Moz2D surfaces instead of Thebes. r=Bas
This commit is contained in:
parent
df8c35f9a9
commit
3b444e24fd
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user